textmachine/platform/docs/platform-PROGRESS.md

165 KiB
Raw Blame History

Журнал зоны «Платформа»

Весь прогресс платформы — ЗДЕСЬ (решение владельца 04.08): пинги, итоги сессий, открытые вопросы, предложения на ратификацию. В docs/PROGRESS.md платформа не пишет; оркестратор читает этот журнал при каждом лендинге зоны (свип «решений владельца» — норма D39.99 п.4).

ФИКС-РАУНД ПО ДИСПОЗИЦИЯМ ОРКЕСТРАТОРА ИСПОЛНЕН — 13 фиксов, 9/9 посадок пойманы, одна находка воркфлоу ОПРОВЕРГНУТА исполнением, канон 0.6.0 принят (сессия платформы, 28.08, после записи ниже)

Диспозиции пришли двумя сообщениями оркестратора (28.08) + третьим — канонная половина полосы (0.6.0). Всё исполнено, кроме ДВУХ пунктов с несогласием (аргументы ниже — обе позиции по норме «несогласие говори»).

Фиксы в дереве (сверх сданного пака; каждый с пином, посадки — в копии ~/tm-p9-mut2)

# Что Пин Посадка
F1 MAJOR(а) 1 МиБ: ingest.EncodeDecisions рендерит с SetEscapeHTML(false) (документ читает движок, не браузер; выбор обоснован в комментарии) + жёсткий гейт: рендер сверяется с зеркалом движкового капа ingest.MaxDecisionsDocument ДО спавна → ErrBankDocumentTooLarge413 (остаточная конвертная полоса ~40 байт закрыта гейтом, слово всегда канонное) TestTheRenderedDocumentDoesNotInflateEscapableBytes (ingest) · TestARenderedDocumentOverTheEngineCapIsRefusedBeforeTheSpawn (runs, движок НЕ спавнится) · TestARenderedDocumentOverTheEngineCapAnswers413 (httpapi) M6 (возврат json.Marshal) и M7 (снятие гейта) пойманы топично
F2 MAJOR(б) мьютекс: lockBook(ctx) — одноместный канал вместо sync.Mutex, ожидание наблюдает контекст; бюджет двери ставится ДО очереди (накрывает ожидание+вызов); Start/Resume передают свои ctx; отмена в очереди корректно декрементит refcount TestAWaiterWhoseContextEndsLeavesTheBookQueue (+ leak-тест расширен) M11 (ожидание игнорирует ctx) поймана
F3 Р1 окно стопа: ReadBookForRun вырос полем LiveRunAwaitingBank (живая строка в awaiting_bank); предикат двери — HasLiveRun && !LiveRunAwaitingBank; Start по-прежнему держится на HasLiveRun (вторая строка сломала бы runs_one_live_per_book); худший случай окна — движок ещё дожёвывает → честный класс 12 → 503 «повтори». Довод в комментарии переписан, противоречие с reconcile.go:1122 разрешено в пользу кода TestTheDoorOpensOnTheSigningStopWindow (фикстура — как control_test: журнальный awaiting_bank без finished_at); обратная сторона держится старым TestCorrectionsRefuseWhileTheBookIsBeingTranslated M8 (старый предикат) поймана — refuse-тест при этом остался зелёным
F4 Р2 миграция 00026: два UPDATE сведены к ОДНОМУ — draft_before := chapters_before для ВСЕХ строк (та аппроксимация, которую ревью само проверило как самосогласованную для finished): пере-снятие БАЗ ПОСЛЕ работы прогона — единственный источник вечного недоезда 2·p_e — удалено; заодно умер и dispute про READ COMMITTED между двумя стейтментами (стейтмент один). Остаток по эпохам старого chapters_before честно назван в комментарии миграции. migrations.sha256 пере-подписан (миграция не релизнута — слово оркестратора) пин исполнением невозможен (тестовые БД наливаются миграциями ДО данных — старая семантика юнитом задним числом непроверяема); держится формулой + комментарием — (названо, не скрыто)
F5 Р5 presence-vs-null: все строковые члены wireCorrectionnullableString (парный nullableInt); явный null на любом = malformed ТИПА (рефьюз до правил присутствия); правила присутствия (id×tuple, dst/kind на decline) считают КЛЮЧИ +3 кейса в TestACorrectionRequestIsValidatedWholeWithPointers (null-src при id · null-dst на decline · null-action) M10 (снятие null-гейта) поймана
F6 Р6(i): комментарий SIGKILL-ветки переписан честно (ветка достижима только когда SIGTERM НЕ отработал; полу-приземлённая пара без отчёта — остаток в PD-407) — (комментарий)
F7 Р6(ii): bankStopGrace 10 с30 с, число обосновано замером движка в комментарии (11.3 с непрерываемого фолда на документе-максимуме, ×2.5 запас на медленный хост) — (константа с доводом)
F8 Р6(iii): связка «ручка TM_PLATFORM_RUN_BUDGET × движковый кап 5000×11.3с» и цена понижения названы комментарием у бюджета двери (механизм не строился — слово оркестратора)
F9 Р7: Service.SweepCorrectionScratch() — подметание bank-corrections-*.json на буте (вызов в композиционном корне tmplatformd ДО подъёма HTTP), файлы вне маски не трогаются TestBootSweepsOrphanedCorrectionDocuments. ⚠ Честно: вызов ИЗ main юнитом не запинен — мутация «не звать на буте» ловится только чтением M14 (маска мимо) поймана
F10 Д5: комментарий spawn.go о сбросе --verify-bank переписан с упразднённого D39.144-контракта на настоящее основание (память v16 покрывает карту; старое основание питало дырявый гард — названо в комментарии)
F11 Н5 hello: при resuming hello несёт last клиента, не голову истории (свежий коннект — голову, как и from четырьмя строками ниже) TestAResumingHelloCarriesTheClientsOwnWatermark (+ свежий коннект отдаёт голову) M13 поймана
F12 Н1-гард: Resume под мьютексом сверяется с новым pgstore.LatestRunID (тот же порядок, что lastRun) — не-последний прогон получает ErrNotResumable с человеческим доводом; реконсилерский RestartRun в гарде не нуждается (живой прогон всегда последний по started_at: пока он жив, новый не стартует) TestAnOlderRunCannotBeResumedOverANewerOne (Now сдвигается между стартами — фикстурный Now дал бы одинаковый started_at и флейк по случайному id) M12 поймана
F13 Канон 0.6.0 (третье сообщение): ContractVersion → 0.6.0; комментарий wireProgress переписан (сквозная доля и stage теперь КАНОННЫ, открытый словарь; оба условия исключения шапки — вывод платформой из тех же счётчиков и открытость — коду отвечают, проверила); протухший абзац про stop_requested заменён на «ни одного члена впереди канона»; комментарий у теста строки библиотеки сужен до правды (сам тест не тронут) гейт версии (reading_test) снова зелёный

Два НЕСОГЛАСИЯ с диспозициями (норма «говори»)

  1. Р4 (limitedBuffer не убивает чайлда) — находка воркфлоу ОПРОВЕРГНУТА исполнением, фикс ОТКАЧЕН. Посадка M9 (kill вырезан) прошла пин за 0.09 с — чайлд умер сам; исходник Go называет механизм прямо: копирующая горутина exec закрывает читающий конец при ошибке Write (os/exec/exec.go writerDescriptor: «pr.Close() // in case io.Copy stopped due to write error») → EPIPE на следующей записи. Агент экстраполировал семантику StdoutPipe (там drain() Kill действительно нужен — exec ничего не закрывает за ручного читателя) на Stdout=io.Writer и НЕ исполнял. Мой добавленный было kill снесён (он был бы кодом под ложный довод); исходный комментарий limitedBuffer был ВЕРЕН и расширен ссылкой на опровержение; поведение запинено живьём: TestAnEndlessBankApplyIsRefusedRatherThanRead (0.1 с; посадка M9b «кап перестал отказывать» валит его таймаутом). Это второй случай за ревью, где замер бьёт рассуждение — в обе стороны.
  2. Р2-dispute (READ COMMITTED между двумя UPDATE миграции) — строкой НЕ заведён: фикс F4 свёл миграцию к одному стейтменту, окна больше не существует.

Регистр и якоря

  • PD-400.2 пере-описана честно (снято «ни ложного слова», мульти-репличный суб-кейс с ложным 503 назван прямо; оговорка внесена и в комментарий ветки класса 12) — редакция для акта лендинга.
  • Новые строки: PD-402..PD-406, PD-410 (major: resume не-последнего [read-половина, write-гард закрыт F12] · sticky edit_wave/re-sell · chapters_done назад · бездеревная книга С ЗАМЕРОМ достижимости 0.018 с из лога стенда · SSE hello [закрыта F11 — оркестратору решить статус] · Р3-полоса/план движка — АРХИТЕКТУРНОЕ, отдельным паком), PD-407, PD-409, PD-411..413 (minor: SIGKILL-слово+грейс [грейс закрыт F7] · утечка temp-файлов [закрыта F9] · мёртвые колонки классом A второго яруса онтологии-18 · карточка 5 сканов · emitProgress под блокировкой), PD-408 (info: ручки двери). Статусы строк, чьё лечение легло этим раундом (405-замер/406/407-часть/409), НЕ переводила — закрытие актом лендинга, как у PD-401.
  • Гейты регистра: counts.py --check413 строк, 109 открытых (9/33/67), битая форма [], хвост []. Якоря, сдвинутые МОИМИ правками, пере-нацелены (PD-375 runs.go:269, PD-* books.go:1065). ⚠ Для оркестратора: docs/PROGRESS.md:159-160 и 17-seam-inbound-law.md:59 / 25-seam-cold-review.md:7 держат якоря, уехавшие НЕ моими правками (supervisor/book.go — чужие сдвиги) и моей (reconcile.go:1228 → теперь :1246) — файлы твоей зоны, чинить тебе.

Числа финальной батареи фикс-раунда (каждое — командой)

go test ./... -race -count=1 -v с тремя гейтами → EXIT=0, 18 пакетов ok, grep -c -- '--- SKIP' → 0, grep -c '^=== RUN' → 793 (было 781 на сдаче ревью — +12 новых пинов), FAIL|DATA RACE — 0 вхождений; golangci-lint run0 issues; gofmt -l пусто; go vet чисто (в составе линта). ⚠ Промежуточная батарея №2 имела РОВНО ОДИН честный FAIL — старый пин TestResumeIsRefusedWhenTheBookHasAnotherLiveRun поймал, что первый вариант гарда F12 перекрывал канонное слово run_in_flight при живом чужом прогоне; чинился КОД (словоразделение: живой сосед → run_in_flight, финишировавший → ErrNotResumable), тест не тронут. Опись дерева: git status --short -- platform/50 путей (39 M + 11 ??).

ВОРКФЛОУ-РЕВЬЮ ДЕРЕВА P9 ОТРАБОТАНО — 16 линз, оба отложенных MAJOR подтверждены замером, сводка находок для оркестратора (сессия платформы, 28.08)

Заказ владельца (релей 28.08): адверсариальная вычитка дерева воркфлоу-оркестрацией — полоса ×4, дверь ×3, миграция, раскладка кодов (wf_cac14b2f-e84) + гонки данных по 4 траекториям владельца, баг-хант нового кода, стоимость per-request (wf_155de7c3-bb4). Раскладка моделей — по слову владельца: 1×Fable на воркфлоу (самая тяжёлая линза), остальным явный opus/sonnet. 16/16 агентов дошли (0 ошибок), ~2.83M токенов. Мандат: «найди, где рассуждение неверно», каждая находка — severity + file:line + траектория с числами; PD-281, PD-401-остаток и пере-нарезка исключены заданием как названные границы. По находкам НИЧЕГО не чинил — жду слова оркестратора.

Дисциплина честности: пометка «подтверждено прогоном» в траекториях — исполнение АГЕНТОВ (их overlay-тесты и /tmp-замеры в копиях дерева), не моё; я пере-исполнил чтением два клейма своего кода (Р4, Р5 ниже — оба подтвердились) и одним своим EXPLAIN-замером ось стоимости (сошлось, ниже). Полные результаты с траекториями сохранены вне репо: журналы воркфлоу в каталоге сессии (subagents/workflows/wf_*/journal.jsonl).

Два отложенных MAJOR ревьюера приёмки — оба ПОДТВЕРЖДЕНЫ, чинить

  • MAJOR(а) «1 МиБ на двух документах» — ПОДТВЕРЖДЁН тремя агентами с независимыми замерами. Механизм: json.Marshal в ingest.EncodeDecisions HTML-экранирует &/</> (1 байт → 6) и меняет конверт (+~25 Б), так что тело под проводным капом 1 МиБ рендерится в документ НАД движковым капом 1 МиБ. Замер агента: 5000 declines с note из &×160 → тело 1 030 050 Б → рендер 5 030 075 Б → движковый exit 14 → 409 bank_corrections_refused «split it» вместо канонного 413. Полоса законных тел широкая (~550 КБ плотного спецсимволами тела уже перескакивает), а существующий пин TestAnOversizedCorrectionDocumentAnswers413 дыру не ловит — набит кириллицей, которая НЕ экранируется. ⚠ Конфликт линз: два агента первого воркфлоу положили эту ось в «не опровергнуто», рассуждая от omitempty («рендер меньше тела») и НЕ меряя; замер двух других бьёт рассуждение (один из «опровергателей» сам оговорил условие плотности &<>). Бонус-cosmetic туда же: скраб пути (runs/bank.go:146) на этом отказе даёт задвоенную фразу «the decision document the decision document» и пропускает на провод движковый префикс pipeline:.
  • MAJOR(б) «мьютекс без контекста, бюджет после захвата» — ПОДТВЕРЖДЁН (runs/bank.go:94 vs :126, lockBook без ctx :270-291): K одинаковых ретраев дают очередь K×60 с; отменённый клиентом запрос ЖДЁТ в очереди и, дождавшись, делает работу (чтение книги, temp-файл) за мёртвый запрос; в ту же очередь встают Start и Resume — заявление «ждать один вызов движка» (runs.go:242-246) держится только для одного ожидающего. Дёшево лечится ожиданием с наблюдением ctx (канал вместо sync.Mutex).

Находки в МОЁМ коде P9 (сверх двух MAJOR; лечение — после слова оркестратора)

# Вес Что Где
Р1 breaks Окно стопа подписи: bank_stop ставит awaiting_bank БЕЗ finished_at, а HasLiveRun читает finished_at is null → до ближайшего свипа (15 с штатно; до 30 мин на бэкоффе отсрочек) дверь отвечает 409 run_in_flight на экран подписи, который платформа сама только что объявила; соседняя кнопка Resume в том же окне отказывает ДРУГИМ словом («being settled»). Мой довод в runs/bank.go:110-112 («its run is closed») прямо противоречит reconcile.go:1122; состояние строится собственным тестом дерева (control_test.go:598-603). Нашли НЕЗАВИСИМО 3 агента runs/bank.go:109
Р2 breaks Миграция 00026 для прогонов в полёте: пере-снятие баз посреди прогона, уже сделавшего p_e правок, оставляет его финал на runDonerunTotal = 2·p_e — полностью доделанный прогон закрывается, например, 5/7 навсегда. Двух-базовая схема корректна ровно потому, что базы берутся ДО работы прогона; миграция — единственное место, берущее их ПОСЛЕ. + dispute: READ COMMITTED между двумя UPDATE допускает двойное касание строки при конкурентном финише (при штатном деплое одной реплики окно закрыто остановкой старого демона — вес мал) migrations/00026:20-27
Р3 breaks draftWork не моделирует порядок волн движка: continuation над недочерновленной книгой (draft_before ≥ chapters_before+C, напр. прогон-предшественник упёрся в потолок на черновике) даёт draftWork=0, движок продолжает ЧЕРНОВУЮ волну — полоса 0/C весь прогон, stage «editing» на прогоне, который только черновит. Зеркало дефекта, который draftWork чинил readmodel.go:460
Р4 breaks limitedBuffer НЕ убивает чайлда при переполнении stdout — вопреки своему комментарию (контраст: drain() в engine.go:262-272 при том же переполнении явно зовёт Process.Kill); чайлд виснет на записи в полный пайп до чужого дедлайна (~70 с под пер-книжным мьютексом), без дедлайна — навсегда. Подтвердил чтением. + dispute: stderr — НЕограниченный bytes.Buffer (не-тот бинарь по сконфигурированному пути может раздуть демона до OOM; читается всё равно только первая строка) runner/bankapply.go:98-111
Р5 breaks Presence-vs-null дыра валидации: только окна (nullableInt) различают явный null от отсутствия; src/sense/dst/kind/id — голые *string, так что {"id":"X","src":null} и decline с "dst":null,"kind":null проходят гейты, которые канонный oneOf/not-required велит отбивать 400. Подтвердил чтением (сам вводил nullableInt только для окон). Порчи данных нет — лишнее значение не читается; дыра контрактная httpapi/bank.go:48-51, 221-224, 251-259
Р6 dispute Раскладка на ветке SIGKILL: ctx.Err()-ветка (runs/bank.go:132) достижима ТОЛЬКО когда SIGTERM не отработал (процесс убит по WaitDelay) — а это единственный путь, оставляющий полу-приземлённую пару БЕЗ отчёта, т.е. адресат bank_corrections_incomplete, отвечаемый общим 503; мой комментарий описывает соседнюю ветку. + bankStopGrace 10 с КОРОЧЕ самого длинного непрерываемого участка движка (11.3 с на документе-максимуме) — грейс истекает до фазы записи. + runBudget — операторская ручка свипа: понижение (к чему подталкивают комментарии) делает легальный документ-максимум навсегда неприменимым (вечный 503 вместо «split it») runs/bank.go:132, runner/bankapply.go:40
Р7 cosmetic Утечка bank-corrections-*.json в StateDir при нечистой смерти демона (SIGKILL/OOM/обрыв грейса деплоя): cleanup только на defer, никто каталог не подметает; до 1 МиБ пользовательских решений на файл, бессрочно runs/bank.go:250
Р8 Формулировка PD-400.2 (accepted-risk) требует правки: на мульти-реплике класс 12 может быть НАСТОЯЩИМ многочасовым прогоном соседней реплики (её Start видит свой мьютекс и чистый runs) — слово 503 «transient holder» и мой лог тогда ЛОЖНЫ, канонно верное слово — 409 run_in_flight. «Ни денег, ни порчи» держится; «ни ложного слова» — НЕТ. Риск остаётся принятым (v1 = одна реплика), но акт лендинга должен описать его честно runs/bank.go:27-39, 182-189

Находки в НАСЛЕДИИ платформы, вскрытые ревью (не код P9; полоса и дверь на них стоят)

# Вес Что Где
Н1 breaks Resume НЕ-последнего прогона (Resume пропускает любой stopped без проверки последнести; lastRun = started_at desc; RestartRun не трогает started_at): (i) полоса возобновлённого открывается на ЧУЖОЙ работе — 2/2 при нуле своих пассов (клэмп режет только >1, не двойной счёт до 1); (ii) карточка, кадр статуса и КАЖДЫЙ progress-кадр живого прогона считаются по ЧУЖОМУ финишировавшему — «ready» и замороженный бар, пока живой прогон тратит деньги. 4 агента, overlay-прогоны reconcile.go:1216, readmodel.go:487, runs.go:843
Н2 breaks edit_wave sticky-true × оператор убрал редактора: прогон делает 100% купленного и закрывается ready на 50% со stage «editing»; chaptersDone (edit-колонка) мёрзнет → ChaptersLeft не падает → шкала повторно продаёт уже переведённые главы (симптом PD-202, записанной fixed); follow-up прогон над этой покупкой читается 0/C с первой секунды. Обе фразы комментария sink.go:406-409 о собственном коде ложны sink.go:415, readmodel.go:388
Н3 breaks Флип false→true уводит Book.chapters_done НАЗАД (finishedUnits через ЖИВОЙ флаг): 40/100 → 0/100 одной транзакцией при росте ревизии — клиент обязан отрисовать спад; ChaptersLeft раздувается обратно → предлагает купить купленное. PD-316-класс на непокрытом триггере (пин ловит только admission). Крайний случай: книга, полностью начерченная под false, НЕдочитываема редактором никаким действием API (ChaptersLeft=0 → прогон не допускается → флип недостижим) sink.go:415, readmodel.go:388, books.go:981-983
Н4 breaks Книга без материализованного дерева: полоса (вся из chapters) читает 0/total весь прогон при исправно доезжающих progress-событиях; комментарий sink.go:219 («счётчики придут из progress-события») ложен уже в HEAD. + dispute: runs.draft_done/draft_total/edit_done/edit_total — 2 писателя, 0 читателей (PD-314-класс, лишняя запись на каждом событии под блокировкой книги; обоснование greatest() на sink.go:444-446 защищает несуществующую полосу) sink.go:219, 137, 447
Н5 breaks SSE hello при переподключении несёт id = state.Position вместо предъявленного last — WHATWG-клиент фиксирует новый Last-Event-ID ДО получения догона; обрыв сразу после hello теряет кадры навсегда (включая note, которые контракт запрещает терять) и обезоруживает дельта-ремонт (revision из hello выше потерянных строк). Лечение — одна строка: при resuming слать last. Код рядом (stream.go:122-126) сам знает правильное значение stream.go:99

Находки зоны ДВИЖКА (чужая зона — пинг оркестратору, мне не лечить)

# Вес Что Где
Д1 breaks Decline не энтити-широк на обратном пути: отклонённая сущность возвращается в карту/auto-bank/редактору через свой АЛИАС (reverseSectionTerms фильтрует по одному ключу, а mined_rejects получает только src), и память предъявления глушит стоп об этом НАВСЕГДА — нарушен собственный контракт «a declined term never re-enters» (miner_emit.go:59-63); approve симметричной утечки не имеет (кластер через строку банка) mining.go:548, membank/decisions.go:598
Д2 breaks Неидемпотентный decline поверхности подписанного сида, имеющей строку в дельте: первый вызов ПРИНЯТ, повтор ТОГО ЖЕ документа — 409 (гейт decisions.go:374 судит ДО-состояние, которое свёртка сама стирает); при классе 15 предписанный ре-сенд отбивается ЦЕЛИКОМ — обещание сходимости 503-ретрая, на котором стоит синхронная дверь, ломается. Доказано исполнением через СОБСТВЕННЫЙ оракул репозитория (оракул 4 фаззера); фаззер структурно не достаёт (фикс-книга не пересекает сид с дельтой). Лечение: судить по ПОСТ-состоянию, как соседний refuseInertDeclines membank/decisions.go:374
Д3 breaks Потеря/порча маркера выхода после стопа (совместная с платформой): рестарт/ретрай проходит границу банка НАСКВОЗЬ — память предъявления покрывает карту, движок «continuing» одним WARN себе в журнал — оплаченный verify_bank стоп исчезает молча и навсегда (память append-only). Гард LiftBankStop (reconcile.go:1122-1126) писан против движка ДО памяти v16 и этот путь не держит reconcile.go:424, mining.go:216-227
Д4 dispute signature в квитанции двери считается от карты, которую переписывает ЛЮБАЯ граница майнинга (запись карты на mining.go:191 — ВЫШЕ решения о стопе): signature != null не означает состоявшегося стопа; surfaces/undecided дрейфуют между двумя вызовами владельца; undecided: 0 достижим при непредъявленных решениях (кап top-200 вытесняет). У карты ЕСТЬ идентификатор (signaturemap.go:25-29) — шов его не читает pipeline/bankdecisions.go:549-598
Д5 cosmetic spawn.go:159-165 (платформа, но про движок) цитирует упразднённый D39.144-контракт стопа («halts whenever undecided terms remain») — при памяти v16 фактически ложно и питает дырявый гард Д3 spawn.go:159-165

Ось «стоимость» — мои живые замеры + вердикт агента (сошлись)

  • Строка 186 единого бэклога ПРОТУХЛА — рекомендация оркестратору: закрыть. Механизм построен и применён: агент прогрепал ВСЕ call sites writeJSON (коллекции, карточка, capabilities, POST двери; SSE корректно НЕ сжимается). Мои замеры на стенде tmp9stand (команды и заголовки — сырьём): банк 437 Б / 7.2 мс холодным, повтор с If-None-Match304 / 0 Б / 2.6 мс; юниты главы 3008 Б → 740 Б gzip (×4.1); gzip ниже порога 1024 Б честно не применяется; resume SSE за головой → 204 / 1.3 мс. Взамен предлагаю ДВЕ новые стоимостные строки (ниже).
  • Карточка книги — 5 коррелированных сканов chapters на один GET (3 в runRow: draftChapters ×2 + editChapters, +2 в bookColumns: chaptersDone + noteCount), и те же 2 — на КАЖДУЮ строку страницы библиотеки (×100). Эмпирика агента на живом PG 18.4, фикстура в форме миграции 00002, книга 2283 главы: как написано — 1.359 мс; те же числа одним LATERAL count(*) filter(...) — 0.307 мс (×4.4). Мой контрольный EXPLAIN на реальной схеме tmp9stand: 6 SubPlan-ов в плане, 5 исполняются (ELSE-ветка never executed) — форма подтверждена. PG повторные текстовые вхождения подзапроса НЕ дедуплицирует (доказано side-effect-последовательностью), CASE-ветки честно short-circuit.
  • emitProgress повторяет 3-скан агрегат по ВСЕЙ книге на каждое progress-событие (движок шлёт его на каждый разрешённый юнит каждой волны) — ПОД блокировкой строки книги: O(глав × юнитов) вместо O(юнитов), на большой книге — секунды суммарного удержания блокировки за прогон.
  • cosmetic: MkdirAll(StateDir) на каждый вызов двери — место одному разу в конструкторе Service.

Чистые оси (проверено — не опровергнуто)

Линза bugs:service-and-seams0 находок (проверены: cleanup temp-файла по всем выходам; редакция refusals — единственная ветка с путём; вердикт-таблица против всей полосы exit.go; ключи только на translate; refcount lockBook; SpendBaseline из колонок ПОПЫТКИ; согласованность bankCountsTx; проекции без утечек словаря/путей; build/vet/тесты). Сквозные not_refuted (по многу агентов): взаимоисключение «дверь × спавн» в заявленную сторону ДЕРЖИТСЯ на одной реплике (все 5 путей спавна упираются в finished_at is null = предикат HasLiveRun); правило одного писателя двух файлов решений; сходимость повтора того же/другого документа при ЦЕЛОМ гейте Д2; SIGTERM после записи не теряет квитанцию (Exited=true глотает ctx.Err — совпадает с диском); идентичность термов через пересборку банка (id из ключа уникальности); сериализация чеканки кадров и штамповка ревизий чисты; чтения на одном снимке; идемпотентный ключ Start не клинит за очередью мьютекса.

Финальная батарея по дереву (после всех приёмочных правок; дерево ревью НЕ меняло)

go test ./... -race -count=1 -v с тремя гейтами → EXIT=0, 18 пакетов ok, SKIP=0, ^=== RUN = 781; DATA RACE — нет. (На сдаче было 775 — рост на приёмочных доборах, число командой.)

Вопросы/предложения оркестратору

  1. Диспозиция Р1Р8: что чиню в этом дереве до лендинга, что строками регистра. Готов завести пакет строк PD-40x по всем группам после твоего вердикта (не завожу до слова — рядом лендинг).
  2. PD-400.2: скорректировать формулировку accepted-risk по Р8 (снять «ни ложного слова», описать мульти-репличный суб-кейс) ДО акта лендинга.
  3. Строку 186 закрыть (замер выше), взамен — две стоимостные строки (5-скан карточка ×100 на библиотеку; emitProgress O(глав×юнитов) под блокировкой) куда решишь.
  4. Д1Д5 — пинг бэкенду твоим каналом; Д2 ломает обещание, которое МОЯ дверь даёт на проводе (сходимость ретрая 503) — до его лечения в движке слова канона §applyBankCorrections о ретрае верны не для всех документов.
  5. Н1Н5 — наследие: Н1 (resume не-последнего) и Н5 (hello id, лечение в одну строку) выглядят дешёвыми и болезненными; Н2/Н3 упираются в продуктовое решение о смене формы конвейера на живой книге.

ПАК P9 ОТРАБОТАН — дверь правок банка смонтирована, ключи едут, полоса сквозная; цепь живого прогона ПРОБИТА живьём (сессия платформы, 27.08)

Дерево передаётся на лендинг. Опись: git status --short -- platform/ → 31 изменённый + 9 новых файлов, все в зоне; вне platform/ не тронуто ничего.

Таблица комплектности против §3 (пункт → сделано → каким ИСПОЛНЕНИЕМ подтверждено)

§3 Что сделано Исполнение
§3.1 дверь POST /v0/books/{bookId}/bank/corrections в contractSurface (монтаж по Deps.Bank, кап тела = канонный 1 МиБ = DefaultMaxBody); строгий декод (DisallowUnknownFields + запрет хвостовых байт), вся канонная валидация формы с JSON Pointer'ами; Capabilities.bank_corrections_enabled = факт монтажа; словарь шва ingest/bankdecisions.go (запрос v1 / отчёт v2, аллоулист); канал runner.BankApply (прямой чайлд, SIGTERM-грейс, потолок чтения); вердикт runs.bankVerdict; квитанция-проекция с переводом edit_wave→refinement и отказом на неизвестное слово; refusals[] в конверте Problem + коды bank_corrections_refused/bank_corrections_incomplete живой пробой — docs/p9/door-live-probe.md (превью → правка → ретрай already_applied → отказ 409 с указателем → resume → 409 run_in_flight при живом прогоне, тела дословно); юнит-пины internal/httpapi/bank_test.go (7 на сдаче; 9 после приёмочных доборов — превью и обрыв на потолке), internal/runs/bank_test.go (6), internal/ingest/bankdecisions_test.go (2); посадки M1, M2
§3.1 раскладка кодов заказанное: 14→409 bank_corrections_refused+refusals[] · 15→503 bank_corrections_incomplete · 12→409 run_in_flight · тело>1МиБ→413 · >5000 и форма→400. Моя половина с доводом: 13→503 service_unavailable (не мигрирован — оператор, транзиентно; различим от 15 по коду) · 19 и незнакомые члены полосы→503 service_unavailable (рассинхрон сборок; какое из двух других ремеди — неизвестно по построению) · 10/11→500 (оба входа глагола рендерит платформа) · exit 5 и таймаут бюджета→503 service_unavailable (рестарт деплоя; SIGTERM-контракт глагола graceful). Три ремеди («пере-реши»/«повтори то же»/«позови оператора») не сливаются пин-таблица TestBankVerdictKeepsTheRemediesApart + TestTheDoorsFailuresKeepTheirRemediesApart; посадка M1 (слияние 15 в 503-generic) поймана; опровергатель кодов: «(а) слияние ремедий — не опровергнуто по всем девяти строкам»
§3.2 синхронность вызов синхронный, бюджет = runBudget() (60 с — класс вызовов движка); пер-книжный мьютекс lockBook в runs.Service, его берут corrections И Start И Resume (Start — та же гонка спавна, что resume); проверка живого прогона — ПОД мьютексом; гейт готовности книги (readyToTranslate) — как у Start (находка опровергателя) TestAResumeWaitsOutALiveCorrectionCall (resume ЖДЁТ живой вызов двери, канал-гейтед фейк); TestCorrectionsRefuseWhileTheBookIsBeingTranslated; живьём — шаг 11 пробоя (409 run_in_flight на живом прогоне); синхронность ДЕРЖИТСЯ: живой вызов двери на стенде — доли секунды, потолок глагола 5000 подобран движком под таймаут вызывающего
§3.3 ключи TM_PLATFORM_ENGINE_KEYS_PATH (абсолютный или отказ на буте; ⚠ суффикс _PATH, не _FILE*_FILE в зоне значит «файл со значением секрета», гейт TestEverySettingThisServiceReadsIsPrinted это и поймал) → runner.TranslateArgs кладёт --keys-file ТОЛЬКО на translate; в окружение юнита ключи не кладутся; пусто = WARN на буте TestTheDeploymentKeyFileReachesTranslate, TestTheSpawnedUnitCarriesTheDeploymentKeyFile (argv юнита + отсутствие ключей в Env); живьём: движок с несуществующим файлом падает громким «--keys-file … cannot be read», с файлом — пре-флайт пройден (лог пробоя); посадка M3 поймана
§3.4 полоса ОДНА монотонная доля через обе волны: done = draftBar + lastBar, total = draftWork + ceiling (редактор) / ceiling (без), где draftWork = clamp(chapters_before + ceiling draft_before) — знаменатель считает работу ЭТОГО прогона (правка по находке опровергателя: continuation поверх начернённого задела кончал ready на 50%); две базы в StartRun, пере-базирование при снятии стопа УДАЛЕНО; подпись progress.stage (drafting/editing, открытый словарь); кадр progress и старт-квитанция несут то же; миграция 00026 (live-прогоны — обе базы пере-сняты верными предикатами, законченные — аппроксимация, названо в самой миграции) живьём: 0/6 drafting → стоп 3/6 editing → resume 3/6 (БЕЗ обнуления) → ready 6/6 (лог пробоя); пины TestTheBarIsOneMonotonicFractionThroughTheSigningStop, TestARunOverADraftedBacklogOwesOnlyTheLastPass, TestADraftOnlyDeploymentCountsItsOneWaveOnce, TestASecondRunsBarStartsAtZeroOverAHalfFinishedBook, TestTheRunsBarNeverExceedsWhatItBought; посадки M4, M5 пойманы
§3.5 PD-399 pending_decisions/complete сняты со всех трёх носителей (BankCounts+кадр EventBank, wireBankPage, подзапрос к мёртвой bank_decisions ушёл); пин ПЕРЕПИСАН на отсутствие TestTheBankAggregatesRideOnTheFirstPageOnly пинит ОТСУТСТВИЕ; живьём: GET /bank на стопе и после прогона — полей нет (лог пробоя, шаги 5 и 13); строка PD-399 → fixed
§3.6 конвенция пути runner.projectDB() и парс book.yaml УДАЛЕНЫ; путь банк-экспорта берётся из конверта artifacts.bank_export, который движок публикует в manifest --json (движковая половина — d1eb8a9); refreshBank кормится манифестом той же refresh-пачки; движок без конверта = громкий отказ, долг ретраится TestTheBankIsReadAtThePathTheEnginePublished, TestAnEngineWithoutTheEnvelopeIsAFailureRatherThanAnEmptyBank; живьём: банк пробной книги материализовался по опубликованному пути (шаг 13)

Числа сдачи (каждое — командой)

  • Батарея с ТРЕМЯ гейтами (TM_PLATFORM_TEST_DSN · _ENGINE_BIN+_BOOK_TEMPLATE · живой пользовательский systemd): go test ./... -race -count=1 -vEXIT=0, 18 пакетов ok, grep -c -- '--- SKIP' → 0, grep -c '^=== RUN' → 775; линтер golangci-lint run0 issues; gofmt -l пусто, go vet ./... чисто. Лог — ~/tm-p9-work/final-battery.log (вне репо).
  • Тест-функции зоны: grep -rh '^func Test' platform --include='*_test.go' | wc -l561 (HEAD) → 580.
  • Регистр: python3 docs/scripts/counts.py --check401 строка, открытых 97 (на сдаче 3/27/67; после пере-взвеса PD-401 приёмкой — 3/28/66); было 398/96 — PD-399 закрыта, PD-400/PD-401 заведены; «битая форма: []», хвост чист. ⚠ Первая редакция этой строки называла «400 строк» — снято пере-счётом ревьюера, число выше — командой.
  • Миграции: 00026 добавлена, отпечаток в migrations.sha256; pgstore.Migrate гонялся каждой тестовой базой батареи (сотни накатов за прогон).
  • Посадки мутаций — 5, пойманы 5/5, в копии с каноном (cp -a --parents platform docs/architecture/14-api-contract, скрипт ~/tm-p9-mut/run-mutations.sh, логи ~/tm-p9-mut/*.log), вердикт по ДЕЛЬТЕ против чистой базы ТОЙ ЖЕ копии (база EXIT=0, FAILS пусто) и по ТОПИЧНОСТИ:
# механизм что посажено что упало (ровно топичный пин)
M1 дверь класс 15 слит в ErrBankUnavailable TestBankVerdictKeepsTheRemediesApart
M2 провод кортеж перестал требовать sense TestACorrectionRequestIsValidatedWholeWithPointers
M3 ключи Cfg.KeysFile не доезжает до argv TestTheSpawnedUnitCarriesTheDeploymentKeyFile
M4 полоса знаменатель снова 2×ceiling TestARunOverADraftedBacklogOwesOnlyTheLastPass
M5 полоса возвращено пере-базирование на снятии стопа TestADraftOnlyDeploymentCountsItsOneWaveOnce

Живой пробой (§4.2) — цепь срослась, и за $0

Полный лог — docs/p9/door-live-probe.md. Суть: книга через живой интейк → прогон до банкового стопа → превью → правка → ретрай (already_applied) → отказ 409 с указателем → resume → 409 run_in_flight при живом прогоне → ready → банк следующей границы несёт правку (方源 → approved «Фан Юань-П9», задеклайненная поверхность исчезла из предложений). ⚠ Провайдер — локальная $0-заглушка (local-модель из models.yaml), потому что в файле ключей деплоя нет ни одного живого провайдерского ключа — движковый пре-флайт называл недостающие ключи по имени для всех шести облачных провайдеров (значения ключей в сессию не читались, гардрейл .env цел; замер — отказ резервации при потолке $0.000001, ДО вызова провайдера). Ось «деньги»: леджер стенда сверен ДВУМЯ путями на нетривиальном состоянии (3 холда/3 возврата/3 расчёта) — CLI balance и сырой SQL сошлись до цента ($25.000000).

Опровергатели (§4, заказ) — 2 агента, обе панели принесли «ломает», всё абсорбировано

  1. Раскладка кодов. «Ломает»: у двери не было гейта готовности книги (не-готовая книга доезжала до движка и возвращалась 500-ложью «наш дефект») — починено (readyToTranslate под мьютексом → 409 book_not_ready). «Спорно»: транзиентные держатели флока вне сериализации (границная материализация, ручной tmctl) читаются словом run_in_flight; мьютекс внутрипроцессный (мульти-реплика теряет сериализацию) — заведено PD-400, лечение вне заказа. Утечка пути темп-файла в refusals[].detail на движковых капах — починено (редакция пути в ApplyBankCorrections). Косметика: SIGINT вместо SIGTERM — починено (syscall.SIGTERM); пустой rejected при exit 14 — гард добавлен; хвостовые байты за JSON — отвергаются (dec.More()). ПРИНЯТО БЕЗ ПРАВКИ с причиной: since_chapter: 3.0 (валидный integer по JSON Schema) реализация 400-ит — генерённые клиенты целых через точку не шлют, названная узость; item-код missing на присутствующем-но-пустом члене — словарь item-кодов открыт.
  2. Форма полосы. «Ломает» №1: continuation поверх начернённого задела — ready на 50% с вечным draftingпочинено (draftWork в знаменателе и в stage; пин + посадка M4). «Ломает» №2: бэкфил замораживал полосу легаси verify-прогонов — починено (миграция пере-снимает обе базы live-прогонов верными предикатами; для ЗАКОНЧЕННЫХ легаси — названная аппроксимация в тексте миграции). «Спорно»: флип edit_wave при живом прогоне двигает знаменатель — заведено PD-401 (окно секунды, лечение трогает словарь шва). ПРИНЯТО С ПРИЧИНОЙ: пере-нарезка внутри прогона обнуляет полосу (снос resolutions — правда о пере-резанной книге, осознанное исключение); stage='editing' на банковом стопе (статус awaiting_bank на экране первичен); старт-квитанция читает «последний прогон книги» (вставка видна в своей транзакции, гонка требует регресса часов).

Диспозиции по норме §3 п.8 (греп открытых строк по ПОЛНЫМ путям моих файлов — 46 совпадений)

  • PD-399 — ЗАКРЫТА этим паком (см. §3.5, пин назван в строке).
  • PD-370 — предлагаю ЗАКРЫТЬ приёмке: зонная половина закрыта 22.08, контрактная — минором 0.5.0 (D39.161: ноль вхождений отменённой модели в каноне), ратифицированная замена (дверь правок) построена этим паком. Закрытие — акт лендинга, не зоны: лекарство контрактной половины не в моём дереве.
  • PD-281 — остаётся open, дописка внесена: сквозная форма сменила знаменатель, но прогон над книгой, полной в обоих проходах, по-прежнему невидим до ready; канонному минору полосы НЕ наследовать «the fraction always reaches one» без оговорки.
  • PD-396 — остаётся (вопрос владельца по строке); замечено: счёт нерешённости теперь едет квитанцией двери (signature), UnsignedBankTerms так и мёртв — снятие поля не брал (не в §3).
  • Остальные 42 совпадения (PD-6…PD-397 по списку грепа) — оставлены: совпадение по файлу, не по механизму — пак их механизмов не трогал; полный список воспроизводится: python3 -скриптом по DEFECT_REGISTER.md (колонка «Где» × список файлов описи).

Чего в паке НЕТ (по §3.7 — пропуски подписаны)

Читающая сторона банка (221/224/226 — на стопе провод банка ПУСТ, видно живьём в пробое, шаг 5) · sqlc · строка 198 · PD-375…PD-398 кроме PD-399 · воркер решений (синхронность ДЕРЖИТСЯ — замер, не рассуждение: живой вызов двери — доли секунды при потолке, подобранном движком под таймаут) · снятие обхода --verify-bank из пинга №21 (не в §3; bank_released остался в спавне и чтениях глав).

Obstacle — что НЕ удалось и что НЕ проверено

  • Живой пробой на ОБЛАЧНОМ провайдере не удался: в файле ключей деплоя нет ни одного живого ключа (deepseek/zai/kimi/gemini/mistral/openai — все названы движком отсутствующими; grok — упёрся в конфиг аддитивного биллинга раньше ключей). Цепь пробита на local-заглушке — она доказывает ШОВ (дверь → глагол → файлы → resume → пере-сбор банка), но НЕ качество и НЕ поведение под латентностью настоящего провайдера. Строка 202 «книга насквозь по-настоящему» упирается теперь ровно в ключи.
  • Таймаут-ветка двери (SIGTERM по бюджету) и класс 15 живьём не воспроизводились — юнит-пины есть, живого файлового отказа не строил.
  • bank_corrections_enabled: false ⇒ 404 живьём не гонял (нужен второй демон без движка) — юнит-пин TestAnUnmountedCorrectionDoorAnswers404AndSaysSoInCapabilities.
  • Стенд-эффект на батарею: живой юнит стенда оставил tm-runs.slice без контроллеров памяти — TestARunIsBoundedByItsOwnCgroup падал, пока слайс не сброшен (systemctl --user stop tm-runs.slice); это среда, не регрессия — на чистом слайсе зелёный. Приёмке знать при пере-прогоне.
  • Пробные артефакты вне репо: ~/tm-p9-work/ (стенд, логи батарей, fake-провайдер), ~/tm-p9-mut/ (копия с каноном + логи посадок). БД стенда tmp9stand на локальном PG 5432 — можно сносить. В КАТАЛОГЕ КНИГ стенда остались мои крафтовые книги — репо не касаются.
  • Сырые логи двух опровергателей не сохранены в зону — их отчёты абсорбированы сюда и в PD-400/401.

Вопросы оркестратору

  1. Канонный минор полосы (D39.160: полоса едет паком, механика версии — за тобой): деплой этой сдачи шлёт progress.done/total в сквозной семантике (chapter-passes работы ПРОГОНА) + новый член progress.stage (открытый словарь drafting/editing) — впереди объявленного 0.5.0 по прецеденту Run.stop_requested (v0.go, ⚠-коммент у wireProgress). Канону нужны: пере-описание Progress (снять «restarts from zero», НЕ наследовать «always reaches one» — PD-281), член stage. Кадр progress меняется тем же минором (EventProgress ссылается на ту же схему).
  2. PD-370 — закрытие строкой за лендингом (см. диспозиции).
  3. Провайдерские ключи деплоя — нужен хотя бы один живой ключ, чтобы строка 202 прошла на настоящем провайдере; какие имена ключей движок ждёт — в логе пробоя.

Аддендум приёмки (27.08, вечер) — блокер ревьюера по полосе: причина починена, лендить ли — слово владельца

Ревьюер приёмки (textmachine-29) принёс блокер: прогон, стартовавший при edit_wave = false с переворотом флага ПОСЛЕ старта (движок объявляет форму волн первым progress-событием), делал всю купленную работу с полосой 0/N навсегда — база снята флаг-зависимым предикатом момента старта и не пере-базируется. Мой пак знал механизм (текст миграции 00026 его называл) и вылечил только legacy-прогоны на буте, оставив генератор живым; строка PD-401 его называла, но с заниженным весом и формулировкой «окно секунды».

Сделано по первому заказу оркестратора (до его поправки «жди слова» — работа уже была зелёной, откат по слову, не молча): причина, не следствие — обе базы снимаются на ФИКСИРОВАННЫХ колонках (chapters_before — редакторская, draft_before — черновая, StartRun без CASE по флагу), пара «числитель+база» выбирается ЖИВЫМ флагом в момент чтения (runDone: draftBar+editBar против draftOnlyBar); миграция 00026 переписана (live-прогоны — обе базы на фиксированных колонках); пин ровно на прод-порядок переворота — TestAFlagThatFlipsAfterStartDoesNotStrandTheBar (флаг false ДО StartRun, переворот ПОСЛЕ, вся работа → 2/2). Сценарий блокера сходится: до переворота 0/C, после — draftWork = 0 ⇒ total = C, редактура двигает 0→C, ready C/C.

Побочно вскрыто и починено (класс PD-1): два старых пина recut_test.go пережили снос сегментной модели с ложными словами — TestLiftingTheSigningStopRestartsTheBarFromZero объявлял «Mutation caught: dropping the re-capture from the re-open», а ре-кэпчер снесён и тест зелёный; переименован в TestLiftingTheSigningStopLeavesTheBarWhereItStood с честным свойством и живым mutation-catch (спутать пары «числитель×база»); комментарий TestTheBarAndItsBaselineCountTheSamePass переписан под пары-по-колонкам.

PD-401 пере-формулирована и пере-взвешена (info → minor, переезд в minor-секцию) по слову оркестратора: постоянная слепота платной работы, не транзиентный скачок; лечение в дереве названо в строке, статус open до решения владельца о составе лендинга. Регистр: 401 строка, 97 открытых (3/28/66), оба гейта чисты; полный pgstore зелёный (go test ./internal/pgstore/ -count=1 → ok). Ось денег на нетривиальном состоянии (открытый холд + после расчёта) ревьюер исполнил на этом дереве сам — расхождений нет.

Аддендум 2 (28.08, по слову владельца «техдолг в паке не держим») — PD-400 разобрана по половинам

Половина 1 (слово run_in_flight шире правды) — ЗАКРЫТА в дереве, и лечение оказалось точнее, чем строка думала: под мьютексом и ПОСЛЕ проверки строки прогона класс 12 от глагола прогоном быть не может по построению (Start/Resume ждут тот же мьютекс, реконсилер рестартует только живые строки, которые проверка видит) — значит run_in_flight отвечается ТОЛЬКО из проверки собственной строки, а класс 12 глагола едет 503 service_unavailable «занято, повтори позже» с ERROR-строкой оператору. Пин — обновлённый кейс вердикт-таблицы; -race по четырём задетым пакетам зелёный, линтер 0 issues. Половина 2 (внутрипроцессный мьютекс) — граница v1, названная с условием и ценой в строке и в шапке bank.go: сериализация сужается до пер-репличной при второй реплике; цена — холостая попытка и «повтори позже», не ложь и не деньги; лечение при второй реплике — арбитр в хранилище. Предложен перевод половины в «Принятый риск» словом лендинга. supervisor.go:35 проверен по существу — ЧЕСТЕН для своего дев-пути (ключи там законно едут окружением/наследованием); дописана одна страховочная фраза «прод передаёт ключи аргументом --keys-file; копировать этот канал в прод-спавн — ловушка паритета, которую флаг и закрыл». Сдвинутые этой правкой якоря runs.go пере-нацелены, оба гейта регистра чисты.

ПАК P9 — ЗАПИСКА-ПЛАН (сессия платформы, 27.08, промт docs/PLATFORM_P9_SESSION_PROMPT.md)

План до правок, по §6 промта. Итоги и таблица комплектности — записью сдачи ниже по завершении.

  1. §3.3 Ключи движку. Новый конфиг TM_PLATFORM_ENGINE_KEYS_FILE (абсолютный путь или отказ на буте, как StateDir) → RunnerConfig.KeysFileruns.Configrunner.TranslateArgs получает --keys-file (флаг принимает ТОЛЬКО translatecmd/tmctl/invocation.go:151-157). В окружение юнита ключи не кладутся. Пусто = флаг не передаётся (сегодняшнее поведение), с WARN на буте.
  2. §3.4 Полоса. Форма: done/total пере-определяются как «проходы-главы через ОБЕ волны»: total = 2×ceiling при редакторе (edit_wave), иначе ceiling; done = clamp(главы-с-черновиком draft_before) + clamp(главы-с-последним-проходом chapters_before), каждый clamp в [0, ceiling]. Монотонно по построению (счётчики юнитов только растут, базы фиксированы на старте), база и кап прогона сохранены (комментарий readmodel.go:437-445 чтится). Миграция 00026: runs.draft_before (бэкфил = chapters_before); StartRun снимает ОБЕ базы, ветвление по $3=verify_bank уходит. Подпись «что делается сейчас» — новое поле progress.stage (drafting/editing, открытый словарь, клиент рисует фразу сам) в JSON и в кадре progress. ⚠ Канон 0.5.0 описывает Progress посегментно — канонный минор к смене едет с лендингом (D39.160: полоса ЗДЕСЬ, механика гейта версий — у оркестратора); прецедент поля впереди объявленной версии — Run.stop_requested (v0.go:138).
  3. §3.5 PD-399. Снять pending_decisions/complete с BankPage и EventBank: BankCounts, payload(), wireBankPage, listBank; пин reading_test.go:113 ПЕРЕПИСЫВАЕТСЯ на новый контракт (присутствие total/signed + ОТСУТСТВИЕ снятых полей) — правка с пином по заказу.
  4. §3.6 Дубль конвенции. Движок публикует конверт artifacts (bank_export и др.) в status --json И manifest --json (backend/internal/pipeline/status.go:110-134, лендинг d1eb8a9). ingest.Manifest получает конверт; refreshBank берёт путь из ТОЛЬКО ЧТО прочитанного манифеста той же refresh-пачки; runner.projectDB() и парс book.yaml удаляются. Без фолбэка: старый движок без конверта = ошибка с именем причины, долг ретраится (порядок деплоя «движок первым» — норма зоны).
  5. §3.1+§3.2 Дверь. Маршрут POST /books/{bookId}/bank/corrections в таблице contractSurface, монтирование по Deps.Bank != nil; Capabilities.bank_corrections_enabled = тот же факт; false ⇒ 404. Вызов СИНХРОННЫЙ: обработчик валидирует проводную форму (строгий декод, оба потолка ДО спавна: >1 МиБ → 413 через кап тела маршрута, >5000 и вся форма → 400), рендерит документ движка (tm-bank-decisions-v1, null-окна → 0), кладёт во временный файл под StateDir, зовёт tmctl bank-apply прямым чайлдом с бюджетом RunBudget (60 с — класс бюджета вызовов движка), декодирует отчёт v2 аллоулистом, отвечает квитанцией. Сериализация: пер-книжный мьютекс в runs.Service, его берут corrections И Resume/Start (та же гонка на спавне свежего прогона); проверка «жив прогон» — ПОД мьютексом (ReadBookForRun.HasLiveRun → 409 run_in_flight). Раскладка кодов: заказанное — 14→409 bank_corrections_refused (+refusals[] в Problem), 15→503 bank_corrections_incomplete, 12→409 run_in_flight, тело >1 МиБ→413. Моя половина, с доводом в отчёте: 13 (схема не мигрирована — оператор, транзиентно) → 503 service_unavailable; 19 (класс без номера — рассинхрон сборок) → 503 service_unavailable; 10/11 (сломан вызывающий/ деплой) → 500 internal_error; exit 5 и таймаут бюджета → 503 service_unavailable. Ни один не сливается в неразличимый 500: три ремеди («пере-реши»/«повтори то же»/«позови оператора») различимы по коду. depth: edit_wave→refinement; неизвестный depth движка НЕ форвардится (утечка имени волны) — 500 с ERROR-строкой.
  6. Самопроверка §4: батарея с тремя гейтами на копии-с-каноном (скипы отдельным -v-грепом); живой пробой двери на стенде против настоящего движка (книга → банковый стоп → preview → правка → resume → следующий прогон видит правку; лог в отчёт); посадки мутаций — минимум по одной на дверь/ключи/прогресс, вердикт по дельте и топичности; опровергатели (2 агента): раскладка кодов и форма полосы.
  7. Не делаю: читающая сторона банка (221/224/226) · sqlc · строка 198 · PD-375…PD-398 кроме PD-399 · воркер решений · снятие обхода --verify-bank из пинга №21 (не в составе §3; трогаю bank_released только в чтении полосы).

ПАК P8-REVIEW ПРИНЯТ И ЗАЛЕНДЁН (оркестратор №19, 27.08) — ратификация D39.159

Пак принят целиком: четыре оси, 24 новые строки, 17 дописок, каталог воспроизведения. Тело приёмки — нота D39.159, здесь только то, чего в ноте нет, и что зоне нужно знать для следующего пака.

Что приёмка пере-мерила своим исполнением, а не приняла на слово. · Батарея пере-прогнана с ТРЕМЯ гейтами на своей базе — 18 пакетов, EXIT=0, линтер 0 issues, скипов 0 (счёт снят отдельным -v). Ваши четыре числа воспроизвелись. · ⚠ Движок для гейта живого рендера собран из HEAD, то есть уже с лендингом бэкенда d1eb8a9, которого 24.08 ещё не было. Это сильнее вашего замера: шов пережил переписанную входную дверь. · PD-379 подтверждён чтением: pump получает разрешённого пользователя и до конца соединения строку сессии не смотрит; маршрут — internal/httpapi/v0.go:84. Ваш артефакт честен вплоть до оговорки про 404 у logout-all на дев-профиле. · PD-376 подтверждена СВОЕЙ посадкой: minmax в internal/pgstore/runs.go:588, копия с каноном по вашему же рецепту, чистая базовая линия EXIT=0/FAIL=0 — после мутации батарея ОСТАЛАСЬ зелёной, названный пин не упал. Спор по PD-159 обоснован.

Диспозиции пяти ваших вопросов.

  1. Статусы PD-159, PD-293, PD-361 НЕ пере-открываю. Описанный строкой дефект из кода ушёл — недостаёт не лекарства, а ПИНА, и пробел уже несёт своя открытая строка. Пере-открытие сказало бы «денежный баг вернулся», что ложно, и посчитало бы один пробел дважды. Токен ОСПОРЕНО(PD-N) ратифицирован как стоячий инструмент — с условием двусторонней ссылки, которое вы уже выполнили (проверил все три пары). Инструмент хороший: он держит спор грепаемым вместо прозы.
  2. Обе правки ратифицированы — норма §3 п.3 и эррата §13. Отдельно одобряю дисциплину эрраты: абзацы политики оставлены до закрытия PD-379. Переписывать обоснование раньше, чем закрыт дефект, значило бы задним числом объявить нормой то, что дефектом и признано.
  3. Галочку ASVS 7.4.1 пометил сам — эрратой в БАННЕРЕ архива, а не правкой строки. ⚠ Файл docs/archive/platform-PROGRESS-P0-P3.mdВ ВАШЕЙ зоне, не в чужой; чужая для вас — docs/ корня. При архиве правку делает лендер, поэтому сделал я, но перестраховка стоила вам вопроса.
  4. Норма принята и вписана — ENGINEERING_STANDARDS §3 п.8. Машинная половина заведена строкой бэклога 225 в docs/PROGRESS.md. ⚠ Ваш гейт замерен ПРЕЖДЕ постройки и требует ПОЛНЫХ путей: по именам файлов он даёт 22 совпадения, почти все ложные (main.go, runner.go, config.go есть в обеих зонах), по полным путям — 2, и оба настоящие. Он окупился до постройки: нашёл, что якорь PD-157 (backend/internal/config/book.go:250) убит МОИМ лендингом d1eb8a9 — требование уехало на :321. Пере-нацелил и назвал причину. Симметричное правило дописано в норму: якорь, убитый переездом, чинит тот, чей переезд его убил.
  5. PD-398 — ОТКЛОНЁН замером, строка пере-формулирована. Предложенное n != shape краснит СЕМЬ законных строк: колонки в counts.py читаются С КОНЦА НАМЕРЕННО, и комментарий на :132 приводит ровно этот случай. Числа регистра из-за избытка не врут — PD-99 и PD-197 разбираются верно. Настоящий остаточный риск другой: избыток в ХВОСТОВОЙ ячейке. ⚠ Я воспроизвёл его на себе, пока правил эту же строку: вписал вертикальную черту в ячейку статуса, и open мгновенно стал «иное», а счёт открытых — 95 вместо 96. Экранирование \| парсеру НЕ помогает, он режет по сырому символу.

Что осталось вам и чего я НЕ делал. Строки пака не чинил ни одной — это работа кодового пака. Ваших «чего не проверял» я тоже не закрывал: сырые логи 42 агентских посадок, -race у выживших, «до 17 раз» в PD-377, живая проба PD-96, экономика PD-215, кардинальность лейблов. Они остаются названными пробелами, а не тихими.

Об ошибках, которые вы назвали сами (пять, от овер-атрибуции PLATFORM_DIRECTION до неполной описи): называть их — правильно, и опись, недобравшая три файла из пяти, действительно стоила бы лендеру правки НОРМЫ. Продолжайте так же.

ПИНГ №21 от оркестратора (27.08, D39.158) — обход флага банка стал лишним, но снимать его ТОЛЬКО после движка

Движок теперь сам исполняет модель D39.144: стоп банка срабатывает только на кластере, которого ни один прежний стоп не предъявлял, а возобновление БЕЗ решений продолжает прогон. Персистентная память живёт в движке (схема хранилища v16).

Что у вас становится лишним: снятие --verify-bank при возобновлении, особый случай в спавне и персистентная колонка «банк отпущен» — их работа переехала в движок, где ей место по п.1 закона шва.

Порядок обязателен и односторонний: сначала лендинг движка (сделан) и tmctl migrate по каждой книге, и только ПОТОМ снятие обхода. Обратный порядок — и каждая книга с поднятым флажком перестаёт писать авто-банк ровно в том режиме, ради которого флажок существует. Порядок деплоя «движок первым» это обеспечивает.

Сверх того, к сведению: заведён класс полосы write_incomplete = exit 15 (и «не легло ничего», и «легла половина» — ветвление одинаковое: условие хоста, не книги; повтор безопасен). Отчёт двери — tm-bank-decisions-report-v2. Полоса получила два яруса и гардрейл «разрушительное действие ключуется на КЛАССЕ, никогда на принадлежности полосе» — у вас он истинен де-факто, правки не требует. Машинная таблица стопа .bank-stop.json СНЕСЕНА (читателя не было ни в одной зоне) — если её называют ваши доки, упоминания протухли.

Строки бэклога, которые вас касаются: 221 (джойн «предложено × решено × нерешено» живёт только в движке — экран подписи заставит вас пере-реализовать его закон, чего п.6 не разрешает; лечение — публикация движком, когда экран закажут) · 224 (банк-экспорт на стопе пуст).

Текущее состояние

ПИНГ ОРКЕСТРАТОРА №19 — 23.08, ЗОНЕ ПЛАТФОРМЫ. Три находки, все сверены моими командами; рукой в код не лезу.

  1. Пере-нарезка книги сносит ВСЕ решения юнитов и пересчитывает прогресс из пустоты. internal/pgstore/readmodel.go:127-137=a re-cut drops the resolutions of the previous cut — это не догадка, там собственный комментарий кода. Строку в ваш регистр я не заводил: решать вам, намеренная это семантика пере-разреза или дефект, и что делать со счётчиками, которые после этого показывают ноль сделанного на книге, где работа была.

  2. БЛОКЕР ЖИВОГО ПРОГОНА: движок на SaaS не получает провайдерских ключей — строка 211 единого бэклога, тело там. Ваша половина: путь к файлу ключей едет из конфига платформы в аргументы движка, а дев-супервизор переводится на тот же механизм. Сейчас пути РАЗНЫЕ — internal/ingest/supervisor.go (до-паковые строки 35-36 и 65-67 — «Provider keys reach the engine through it»; комментарий переписан лендингом P9, якорь исторический) наследует окружение платформы, а прод-спавн ставит юниту ровно один элемент (internal/runs/spawn.go, до-паковая строка 168 Env: engineEnv(…); с лендингом P9 ключи едут аргументом --keys-file, якорь исторический). Поэтому стенд зелёный, а прод голодает, и ни один тест упасть не мог. Пока два пути кормят движок по-разному, следующий такой блокер снова пройдёт всю батарею.

  3. Дубль движковой конвенции у вас. internal/runner/artifacts.go (до-паковые строки 65-95 — «neither project_db nor book_id»; projectDB снесён лендингом P9, файл ужался, якорь исторический) сам вычисляет путь БД книги, повторяя backend/internal/config/book.go (до-паковые строки 163-167 — b.ProjectDB = filepath.Join(…); конвенция ушла в конверт манифеста движковой половиной, якорь исторический); смена дефолта в движке тихо уведёт ваше чтение банка на несуществующий путь. Строка 213. Фикс аддитивный и без ломки: движок отдаёт путь артефакта, вы выкидываете свой projectDB(). ⚠ Пере-именование банк-экспорта в фикс-имя — ЛОМАЮЩЕЕ, ему место в окне строки 161, не здесь.

  4. Поле, которое декодируется и не читается. ingest.StatusReport.UnsignedBankTerms (internal/ingest/resync.go:30=UnsignedBankTerms) разбирается из ответа движка и не используется НИ ОДНОЙ строкой продакшн-кода зоны. Либо потребитель потерян при спиле пер-термного пути, либо поле лишнее — решать вам; я называю факт, потому что мёртвое поле в структуре шва читается как контракт.

(Промт P8-REVIEW жив и ждёт слова владельца. ⚠ Правка к этой же записи, 23.08: я объявил в ней ДВА дефекта промта — реальным оказался ОДИН и он ПОЧИНЕН (миграция 00019 названа денежной, хотя это 00019_read_model_debt.sql, долг read-модели; ось 1 по ней ушла бы не туда). ⚠⚠ Второй дефект РЕАЛЕН, и моё прежнее «не воспроизвёлся» было ЛОЖЬЮ — снимаю её здесь же. Я написал зоне «грепа 13 изменённых|6 новых|2166 в промте ноль». Греп СОВПАЛ: строка 42 промта несёт «в дереве живёт НЕЗАКОММИЧЕННАЯ работа полигона (13 изменённых файлов и 6 новых под eval/)». Я обрезал вывод грепа по ширине, увидел начало строки и принял совпадение за отсутствие. Счёт при этом действительно протух: на 23.08 в дереве 14 изменённых и 5 неотслеженных. Дефект ПОЧИНЕН тем же заходом — числа из промта убраны, он теперь ссылается на единственный носитель счёта, а не держит свою копию. Записываю, потому что обещание зоне, исполненное наполовину без объяснения, читается как невыполненное.)

  • ПАК P8-REVIEW ОТРАБОТАН (24.08) — четыре оси прочитаны, кода не тронуто.

    Что уезжает на лендинг (опись пере-снята командой, лендить по ней): git status --short -- platform/M docs/DEFECT_REGISTER.md · M docs/platform-PROGRESS.md · M docs/ENGINEERING_STANDARDS.md · M docs/STACK_DECISIONS.md · M docs/PLATFORM_P8_REVIEW_SESSION_PROMPT.md · ?? docs/p8-review/. ⚠ Три последних — не находки, а правки, и две из них требуют вашего слова: в ENGINEERING_STANDARDS §3 вставлен НОВЫЙ пункт 3 (рецепт копии с каноном и правило «дельта плюс топичность») — это правка НОРМЫ зоны; в STACK_DECISIONS §13 вписана эррата к обещанию «мгновенный отзыв», которое PD-379 опровергает; в промте пака исправлен рецепт копии. .go в репозитории не тронуты (git diff -- platform/ ':!platform/docs' пуст), индекс чист.

    Числа сдачи (сняты ПОСЛЕ последней правки регистра): · python3 docs/scripts/counts.py --check от корня → 398 строк, открытых 96 (3 major, 27 minor, 66 info); было 374 и 72 (1/16/55). 24 новые строки PD-375PD-398, 17 ⚠-дописок к чужим. Чужие статусы и веса не сдвинуты: вся дельта открытых — мои новые строки. · make check с тремя условиями → 18 пакетов, EXIT=0, линтер 0 issues (docs/p8-review/battery-final.log). Скипы лог не считает — секция «did NOT run» печатается только при найденном --- SKIP, — поэтому счёт снят отдельно: go test ./... -count=1 -v с грепом по --- SKIP0. Это и есть недостающий замер к PD-374: на этом хосте выполнимы все три условия. · counts.py --lint → по platform/docs один якорь, и он ЧУЖОЙ и транзитивный: platform-PROGRESS.md:27 целит в backend/internal/config/book.go:163-167, против HEAD там строка 164 — верно, — а красным его делает незакоммиченная работа соседней бэкенд-сессии, двигающая цель на 188. Правку этого якоря я сделал и ОТКАТИЛ: не пере-нацеливать. Прибить его к транзитному положению значит сломать в момент лендинга или отката соседней работы. · Посадок мутаций: мои 16 (все воспроизводимы — plant.py знает поимённо, логи рядом), 7 поймано, 9 выжило; агентских 42 по их таблицам (docs/p8-review/agent-mutations.md), 21/21. Уникальных переживших инвариантов 15, каждый несёт строку.

    Ось → чем закрыта → находки. Предмет каждой оси взят из промта целиком; ниже только отклонения.

    1. Деньги и леджер. Обязательная норма исполнена дважды и на НЕтривиальном состоянии — docs/p8-review/reconcile-with-open-hold.txt (8 строк леджера, ОТКРЫТЫЙ холд $0.06 в момент замера, оба пути сошлись); независимо то же сделал агент оси на своём стенде. Вторая половина нормы (леджер = НИЖНЯЯ граница) проверена отдельно: расход СВЕРХ холда каппится и живёт только текстом в note, который не читает ни один путь кода — internal/pgstore/credits.go:225 плюс ноль SELECT по колонке. Это проектное решение, строкой не заведено. Находки: PD-375 PD-376 PD-377 PD-378 PD-394 PD-397.
    2. Вход, сессии, CSRF — ось, которой не касался ни один пак. Живые пробы на демоне со СВОИМИ короткими потолками, матрица CSRF по маршрутам, посадки, сверка с ASVS 5.0 и RFC. Находки: PD-379 (единственный vuln пака, major) PD-380 PD-381 PD-382 PD-383.
    3. Очередь и джобы. Смотрел не сам блокер PD-169, а его сиблингов И его лечение. Пробы на РЕАЛЬНЫХ функциях с реальным Postgres. ⚠ Пять якорей промта по этой оси сверены и живы дословно. Находки: PD-384 PD-385 (major) PD-386 PD-387 PD-388.
    4. Метрики — исполнением. Снимок в покое → вызванный отказ → снимок → дифф; все три в docs/p8-review/axis4-metrics/. Ответ на вопрос оси «что оператор понял бы по этой дельте»: почти ничего. Переход в stalled по одной /metrics виден; отказ свипа — нет (меняется только гистограмма длительности); гейджи при отказе чтения замирают без признака устаревания; инстанс, у которого чтение не удалось ни разу, отдаёт нули как здоровье. Случаи, где run abandon ОТКАЖЕТ, оператор различает — колонка SPENT печатает «?» ровно при пустой базовой линии, биекция; это единственная находка пака, опровергнутая рефутером по всем четырём состояниям. Находки: PD-389 PD-390 PD-391 PD-392 PD-393.

    Сверх осей — из сверки регистра с деревом: PD-396 (мёртвые поля шва) и PD-398 (гейт формы регистра ловит недостачу ячеек, но не избыток).

    Таблица посадок — мои, вторым рубежом поверх агентских (docs/p8-review/plant.py, логи mutations.log · mutations-full.log · mutations-round2.log):

    # ось что посажено какой пин обязан был упасть упал
    M1 деньги снята пере-проверка «попытка уже заспавнена» в ReleaseUnspawned TestAStaleSnapshotDoesNotGiveBackTheHoldOfAnAttemptThatSpent
    M2 деньги снят кламп по SpendBound в settle TestADeferredSettlementIsNotChargedForTheNextRunOfTheSameBook
    M3 деньги holdTx отвечает nil вместо ErrDuplicateHold TestAHoldThatDebitedNothingIsRefused
    M4 деньги снят гард spent < 0 в Settle носителя нет PD-394
    M5 деньги снят кламп-в-ноль в attemptSpend TestAMeterThatWentBackwardsSettlesAtNothingAndSaysSo
    M6 вход Secure: !c.InsecureSecure: false TestLoginCompletesAndCreatesOurOwnSession
    M7 очередь phaseBudget отдаёт весь проход вместо половины два пина фаз
    M8 метрики снят m.stalledRuns.Set(...) носителя нет PD-389
    M9 метрики снят инкремент sweepUnfinished TestTheRunnersStateIsExposedWithItsUnits
    M10 метрики снят m.abandonedSurfaces.Set(...) носителя нет PD-389
    M11 деньги SpendBound: minmax носителя нет PD-376
    M12 вход абсолютный потолок сессии умножен на 100 в CreateSession носителя нет PD-380
    M13 вход ClearSession выдаёт TTL time.Hour вместо -time.Second носителя нет PD-382
    M14 вход в set ветка ttl < 0 даёт maxAge = 3600 носителя нет PD-382
    M15 вход срок хранения журнала входов 180 суток → 180 ЛЕТ носителя нет PD-383
    M16 вход предикат свипа журнала обезврежен носителя нет PD-383

    Пол по каждой оси выполнен — колонка «ось». Все девять выживших пере-проверены на ПОЛНОЙ батарее против чистой базовой линии ТОЙ ЖЕ копии, не по exit-коду.

    Правило вердикта, которое пере-ранящему знать обязательно: судить по ДЕЛЬТЕ против чистой копии И по ТОПИЧНОСТИ упавшего теста, а не по цвету батареи. Цена забывания оплачена здесь дважды: известный флейк PD-369 дал ложное «пойман», а первая редакция mutations-full.log печатала RED там, где мутация выжила. Правило записано в ENGINEERING_STANDARDS §3 п.3, PD-382 и PD-395.

    Реестр против дерева — 17 ⚠-дописок. Строка open, чьё лекарство уже в дереве, отправляет следующий пак чинить построенное. Предлагаю ЗАКРЫТЬ: PD-23, PD-203, PD-166. Сузить, но НЕ закрывать: PD-162, PD-368, PD-374. Пере-формулировать: PD-6, PD-157, PD-168, PD-90, PD-101. Свести с условием, названным в дописке: PD-251PD-42, PD-250PD-179. Помечены токеном ОСПОРЕНО(PD-N) — статусы паком НЕ менялись: PD-159, PD-293, PD-361. Конвенция токена записана в шапку регистра.

    Аддендумы владельца по ходу (§5 промта) — три, результат:

    1. «Архитектурно чистое решение по PD-395?» → строка ПЕРЕПИСАНА, диспозиция сменилась с «править гейт» на «править рецепт», рецепт исправлен и проверен исполнением, а лечение переехало из эфемерного носителя (промт архивируется при лендинге) в ENGINEERING_STANDARDS §3.
    2. «Посоветуйся со старшим; веди через существующего агента» → два захода старшей модели, оба абсорбированы; дальше вёл сообщением, а не новым агентом.
    3. «Доводи до конца» → рефутер по восьми утверждениям сверки реестра (последний рубеж без адверсариальной проверки) и редакторский аудит сдачи; оба нашли дефекты, оба закрыты.

    Мои ошибки, которые нашли не я, и они того же класса, который пак ловил. (а) Сослался на PLATFORM_DIRECTION §3 как на ратифицированное направление по oapi-codegen, не сверив, что оно ПЕРЕ-ПОДПИСАНО D39.132 в «кандидат» и P7 решил не брать. (б) Дописка к PD-166 описывала механизм, недостижимый в сегодняшнем коде. (в) Сужения четырёх строк оси 34 оказались КРУГОВЫМИ — каждое опиралось на поверхность, несостоятельность которой доказывает соседняя строка того же пака; из-за этого PD-385 стояла minor. (г) PD-379 несла вес major, а лежала в секции minor. (д) Опись изменённого называла два файла из пяти — лендер недобрал бы правку НОРМЫ. Всё исправлено; называю, потому что необъявленная ошибка автора — это находка, которой нет.

    Obstacle. · Чужой демон tmplatformd pid 211037 (порты 8080/9464, база tmstand) — не трогал; пак изолирован своими портами 8099 и 81018114 и базами tmp8rev_*. Соседняя бэкенд-сессия живёт в дереве (18 файлов) — отсюда транзитивный якорь выше. · Первый запуск четырёх осей умер на середине (обрыв сессии плюс Connection lost у одного агента). Копии сверены diff -rq, базы пере-созданы, всё пере-запущено с нуля. · Чего НЕ проверял. Сырые логи 42 агентских посадок не сохранены — их вердикты пере-ранить нельзя, только пере-посадить по описанию; из 21 «пойман» 19 называют конкретный тест, 2 нет. Пере-проверка выживших шла go test ./... БЕЗ -race (для класса «пина нет» вердикта не меняет, но сказано). Не пере-мерены мной: «до 17 раз» в PD-377, живая проба preflight из PD-96, экономика петли PD-215, кардинальность лейблов под нагрузкой. Числа пробы в дописке PD-162 сняты рефутером, лог в артефакты не попал. Клейм «$0.15 против $0.03» СНЯТ — лога не осталось, механизм на его месте доказан грепом.

    Вопросы приёмке.

    1. PD-159, PD-293, PD-361 стоят fixed, а их пины доказывают меньше. Статусы не менял — пере-открыть это одна правка, и она ваша; улика и живые пробелы вынесены новыми строками.
    2. Правка НОРМЫ (ENGINEERING_STANDARDS §3 п.3) и эррата к STACK_DECISIONS §13 сделаны мной в своей зоне, но обе меняют объявленное — нужна ваша ратификация или откат.
    3. Снятие галочки ASVS 5.0 7.4.1 в docs/archive/platform-PROGRESS-P0-P3.md:572 — там она стоит выполненной словами «отзыв прекращает использование», что PD-379 опровергает. Это ЧУЖАЯ зона.
    4. Класс «open, а лекарство построено» стоит зоне ~10% открытых строк. Предложение, оба этажа вне права читающего пака: норма в промты кодовых паков («построил механизм → грепни открытые строки по именам своих файлов, каждое совпадение — диспозиция в отчёте») и, пингом в docs/, пересечение застейдженных путей с якорями открытых строк.
    5. PD-398: malformed() в counts.py ловит только недостачу ячеек — однострочная правка в вашей зоне.
  • P8-FIX ПРИНЯТ И ЗАЛЕНДЕН оркестратором №18 (22.08). Тело приёмки — ратифицированная нота D39.154 (docs/architecture/05-decisions-log.md), здесь не пересказывается. Зоне важно ровно следующее, и этого в ноте нет:

    • Пинг зоны №1 ЗАКРЫТ: якорь 05-decisions-log.md:542internal/pgstore/perf_test.go:13 жив, токен «96% of the page» на месте — правку комментария бенчмарка приёмка приняла.
    • Правку зоной ЧУЖОГО документа (пере-нацеливание двух моих якорей в промте читающего пака после переезда констант) утверждаю и не откатываю: якоря умерли по вине пака, пак их починил и раскрыл это сам, вместо того чтобы обойти красный гейт. Это ровно то поведение, которого норма и требует, — так и делайте дальше.
    • «Скипов 0» у меня НЕ воспроизвелось: три скипа. Не ваша регрессия и не ошибка отчёта — systemdOrSkip гейтит три теста internal/runner достижимостью пользовательского менеджера systemd, а на моём хосте /run/user/1000 нет. Незакрытым осталось то, что рецепт и критерий приёмки объявляли у батареи ДВА гейта, а их три: PD-374, оба носителя поправлены 22.08.
    • Мои одиннадцать посадок мутаций вне вашего списка: убито восемь, выжили три — StalledAfter законно (носитель один), maxAttempts и truncateReason дали PD-373/PD-372. Плюс находка вне карты пака PD-371. ⚠ Две первых редакции МОИХ посадок дали ложное «выжила» — гонял не тот пакет; пере-прогнано. Говорю, потому что необъявленная ошибка харнесса приёмки — находка, которой нет.
    • Числа сдачи в вашем отчёте держатся, кроме одного: «отпечатков миграций 41» — их 25 (grep -c '^[0-9a-f]\{64\}' migrations.sha256); число было названо без команды. Регистр после приёмки — 374 строки, открытых 72 (1 major, 16 minor, 55 info).
    • Открытым уезжает PD-370 (контрактная половина) — не работа зоны, закрывать её здесь было бы подгонкой под критерий приёмки. Согласен с вашей диспозицией. ⚠ Порядок паков вышел ОБРАТНЫМ очереди: промт P8-FIX требовал запуска ПОСЛЕ читающего пака, запущен был раньше. В плюс — названная цена перестановки («блокер живёт всё время читающего пака») НЕ заплачена. В минус — §4.7 релея пуст, и читающий пак пойдёт по только что переписанному коду; его промт про это предупреждён баннером.
  • Эра пака P8-FIX (2122.08) — В АРХИВЕ. Отчёт пака, обе волны ревью, спил пер-термной подписи, инвентарь каналов и obstacle — archive/platform-PROGRESS-P8.md. Ратификация — D39.154, лендинг 31f1f82. Живое из этой эры: четыре открытые строки регистра (PD-370 мажор — контрактная половина · PD-371 · PD-372 · PD-373/PD-374), инвентарь каналов шва в STACK_DECISIONS.md, граница sqlc в BACKLOG.md П-19.

  • Записи акта 5 пака P7, остававшиеся в живом журнале, — ДОСЛАНЫ в archive/platform-PROGRESS-P7.md 22.08: заголовок «эра P7 в архиве» стоял, а тела лежали здесь.

  • Запись оркестратора, 15.08 — P6 + ДОФИКС ПРИНЯТЫ И ЗАЛЕНДЕНЫ (D39.132). Приёмка двумя раундами: панель 5 адверсариальных верификаторов по P6 (две линзы — другой моделью; исполнением, включая живой демон и живой PG) → фикс-лист ФП-1…ФП-8 → дофикс → финальная верификация исполнением: батарея make check под -race с живым PG и ОБОИМИ гейтами пере-прогнана оркестратором — EXIT=0, 17 пакетов, скипов 0; тестов 416 (grep -rh '^func Test' platform --include='*_test.go' | wc -l; HEAD = 359); деньги пере-считаны из сырого леджера стендовой БД двумя путями (сошлись до цента); живая проба рендера пере-снята своим tmctl из HEAD; 2 собственные посадки приёмки на дофикс — обе пойманы (TestAFlaggedBookStillAnswersAboutItsMoney · TestEachOfTheThreeBlockersAloneKeepsABookOutOfTheMigrationList — вторая до дофикса переживала всю батарею). Исправлено оркестратором при лендинге: откачено переименование закрытой строки PD-198 → PD-199 и удалена заведённая под PD-198 строка-дубль с ложным обоснованием (регистр 246 → 245 слиянием; «ID стабилен навсегда»); PD-200 перенесена в «Закрытые — эра P6», PD-180 — в «Открытые — info». Ратификации и диспозиция вопроса PD-241 — тело D39.132.

  • ДОФИКС P6 ЗАКРЫТ — дерево передаётся на лендинг одним пакетом с P6 (15.08). Фикс-лист приёмки ФП-1…ФП-8, раздел «Дофикс P6» ниже. Ни одна находка не опровергнута, но две подтвердились не так, как их описала приёмка. Самая тяжёлая — денежная и на ОБЫЧНОМ пути: движок отвечает exit 2 из status --json про любую книгу с помеченной единицей, а платформа читала это как «движок не ответил», из-за чего расчёт такого прогона откладывался вечно и следующий прогон книги не стартовал. Плюс аддендум владельца 15.08: day_usd убран из ПРИМЕРА шаблона книги. Батарея под -race с обоими гейтами: EXIT=0, 17 пакетов, скипов 0, линтер 0 issues, make vuln чист, 359 (HEAD) → 416 тестовых функций — счёт командами в разделе. Посадки 15 из 15.

  • P6 ПОСТРОЕН — дерево передаётся на лендинг (14.08). Потребительская половина шва эмиттера (П-15) · интейк формы Б (П-14) · дев-стенд с сидом и дев-входом (П-16) · порядок апгрейда движка против деадлока v15 · попутные PD · гигиена зонных доков. PD-113 закрыт — открытых major в регистре НЕТ. Батарея на стенде ~/.local/pgsql (порт 55433) под -race: EXIT=0, 17 пакетов, линтер 0 issues, скипов 0, make vuln чист, тестов зоны 359 → 401 (числа P6; счёт — команды в разделе «Дофикс P6», прежний базис «396 → 403» не воспроизводился, PD-234). Посадки: 20 из 20 в первом круге (три переписаны после разбора переживших) + 6 из 6 на находки адверсариальной панели, одна названа НЕПИНЯЕМОЙ по построению. Живые пробы на настоящем tmctl и на фейке движка с правилом потолка — разделы ниже. ⚠ Три вопроса на ратификацию оркестратору (подробности в разделе P6): внутренняя причина daily_ceiling НЕ проецируется на провод (контракт знает одно значение — PD-199, спек-правка за S4) · направление PLATFORM_DIRECTION §3 предложено ПЕРЕ-ПОДПИСАТЬ (oapi-codegen и sqlc не исполнены, срок «до первого хендлера» пройден) · батарея получила ВТОРОЙ гейт окружения (TM_PLATFORM_TEST_ENGINE_BIN + _BOOK_TEMPLATE), без него один тест честно скипается.

  • P5 ПОСТРОЕН и ДОФИКШЕН по приёмке — дерево передаётся на лендинг (11.08). (→ принят в три раунда и заленден D39.130, 69d485a — запись оркестратора 14.08 ниже.) POST /v0/books потоково с пер-маршрутным потолком тела и своим дедлайном чтения · статусы uploading → parsing → not_started | rejected получили писателей, разбор — $0-команда движка tmctl manifest · POST /v0/runs/{id}/stop|resume с намерением стопа в Postgres ДО сигнала · метрики Prometheus на отдельном слушателе · печать эффективной конфигурации.

  • Приёмка 11.08 (8 находок) → дофикс → кросс-семейное ревью дофикса (5 находок) → ре-чек оркестратора (3 находки, 2 high) → ТРЕТИЙ РАУНД ЗАКРЫТ (14.08): разделы «Третий раунд», «Дофикс-2» и «Дофикс P5» ниже, движение — записками-планами. Батарея на стенде ~/.local/pgsql (порт 55433) под -race: EXIT=0, 16 пакетов, линтер 0 issues, скипов 0, make vuln чист, тестов 261 → 359. Посадки: 10/10 · 6/6 · 6/6 (две пережившие за все раунды — оба раза виноват был слепой пин, переписан пин, не мутация); списки — в журнале. ⚠ Тулчейн 1.26.6 НА РАТИФИКАЦИЮ (→ ратифицирован D39.130), и вчерашний клейм про него был ЛОЖЕН: гейт принимал 1.26.5 (регекс вместо сравнения). Теперь floor держат два механизма — make version-check сравнивает версии, go.mod несёт toolchain go1.26.6, который читает всякая сборка; при GOTOOLCHAIN=auto хост скачает нужный тулчейн, при =local остановится. Само сравнение запинено (internal/gates). ВОПРОС на ратификацию — кто пишет book.yaml при интейке: половина П-9 стоит на нём, раздел «Развилка» ниже. (→ решено D39.130: бета = форма Б, стройка = П-14; движковая форма В = строка 170 единого.)

  • Запись оркестратора, 14.08 — P5 ПРИНЯТ И ЗАЛЕНДЕН (69d485a, D39.130). Финальная верификация исполнением: батарея EXIT=0 на том же стенде · гейт версий живьём отказывает 1.26.5 и go1.27rc1, принимает 1.26.6 и 1.26.10 (sort -V честный) · toolchain go1.26.6 в go.mod · сентинел .tmplatform-books на месте · revision+1 остался ровно у двух заявленных прогресс-писателей синка (мотивированное исключение ратифицировано) · тестов 359, регистр 198, удалённых имён тестов против HEAD нет. Ратифицировано (D39.130): Go-floor 1.26.6 с toolchain-директивой (цена офлайн-хоста с =local названа и принята) · book.yaml при интейке — форма Б (рендер из деплой-шаблона; интерпретация D39.110 §2b с аудит-следом, стройка — следующим касанием зоны), форма В (tmctl init) — строка 170 единого бэклога движку · контракт-диспозиции PD-172/173/174/180 — спек-правкой 0.2.3 задачей S4-промта · PD-196 → дописка строки 165 (различимость классов отказа manifest).

  • Пинг оркестратора, 14.08 (второй) — ЭМИТТЕР ДВИЖКА ЗАЛЕНДЕН (D39.131, 9cfe080): events.jsonl начнёт появляться в каталогах книг. Словарь = ваш events.go с диффом движка (принят приёмкой): StreamVersion 1.1 · Ceiling.Scope: book|day · Finished.outcome += ceiling|stopped · eta_seconds = темп ТЕКУЩЕГО прогона · unit_done.unit = лидерный first_chunk_idx. Ваша половина — П-15 зонного бэклога (маппинг exit 4/5/1019 · unit_done присваиванием · scope · dev-супервизор · порядок деплоя против деадлока v15 — строка 174 единого, РЕШИТЬ ДО деплоя нового бинаря). PD-113/PD-196 в регистре остаются open до П-15 — движковая половина построена, потребительская нет.

  • Пинг оркестратора, 14.08 — гигиена зонных доков по аудит-свипу корпуса, закрыть следующим касанием зоны (вместе с П-14): README.md:85 «тулчейн ≥1.26.5» → 1.26.6 c toolchain-директивой · README.md:87 «River не подключена — П-3» и STACK_DECISIONS.md:23 «River в go.mod НЕ добавлен» — противоречат go.mod и построенной P4-очереди · README.md:47-48 вопрос book.yaml → решён D39.130 (форма Б) · PLATFORM_DIRECTION.md: oapi-codegen «взять — доказано» против ENGINEERING_STANDARDS:59 «кандидат при P1» — оба не исполнены (ручки P4/P5 рукописные), sqlc «до первого хендлера» не случился (PD-44 открыт), «River в go.mod не заводить» отстал — направление пере-подписать честно · DEFECT_REGISTER.md: PD-172/173/174/180 не несут диспозицию D39.130 (спек-правка 0.2.3 задачей S4) · открытые PD-180/185/196 живут в секциях «Закрытые…» · PD-178 стоит после PD-191 (порядок номеров) · PD-99 (fixed кодом) лежит в «Закрытых ратификацией» · путь docs/scripts/counts.py в шапке регистра исполним только от корня репо · веса high/medium-high секций дофиксов против объявленных major/minor/info · STACK_DECISIONS.md:17 называет гейт «make tools-check», хотя version-check отделён (FP5-9) · П-1/П-3 зонного бэклога не знают построенного P4 (вес «Ф3, после контракта» отстал) · хвост (г) третьего раунда — перечислительность мета-пина systemd-гейта — носителя не имеет: завести PD-строку или закрыть явно.

  • P4 «раннер» + дофикс + V2 ПРИНЯТЫ и ЗАЛЕНДЕНЫ — D39.123, код d29e30c (ревью-шапка ниже): транзиентный systemd-юнит на прогон · очередь River с холдом-до-спавна в одной транзакции · реконсилятор с базовой линией расчёта · тейлер events.jsonl с карантином проекции · пять ручек /v0 контракта 0.2.1 · дев-интейк. Батарея с живым PG 18.4 под -race зелёная, скипов 0, тестов зоны 261. Формула аргумента потолка — committed + прирост (PD-158, ратифицирована ПОПРАВКОЙ к пингу оркестратора).

  • Регистр — 245 строк (python3 docs/scripts/counts.py от корня репо; было 246 — лендинг слил строку-дубль PD-198, испр. оркестратором №16 15.08): 178 закрыто · 1 закрыт ратификацией (PD-59) · 4 риском · 62 открыто (17 minor, 45 info), из них 0 major — PD-113 закрыт P6 вместе с приходом эмиттера. Форма — 15 секций (добавлены эра P6 и дофикс P6).

  • Промт P5 ВЫДАН оркестратором 10.08 (PLATFORM_P5_SESSION_PROMPT.md, D39.128): П-9 POST /books (+PD-72 потолок тела; развилка «кто пишет book.yaml при интейке» — вопросом в этот журнал ДО стройки той половины) · стоп/резюм-ручки PD-140 (различение «потолок vs авария» — за эмиттером движка, строки 103/165, его промт выдан параллельно) · наблюдаемость П-11 + печать конфигурации PD-114 · DEFECT_REGISTER секциями (пинг №16). Запуск — по слову владельца. (→ исполнен сессией P5 1114.08, принят D39.130; промт с баннером-исходом — archive/PLATFORM_P5_SESSION_PROMPT_2026-08-10.md.) Эскроу/uncertain (строка 136) — следующим денежным промтом, НЕ в P5.

  • Эры P0P3 (вход OIDC · кредиты · админ-CLI · деплой · фикс-паки) — исполнены и залендены (D39.107/109/112/114); разделы — в archive/platform-PROGRESS-P0-P3.md. Стек и рецепт стенда — STACK_DECISIONS.md; критерии приёмки — ENGINEERING_STANDARDS.md.

(Записи паков P4P6 с дофиксами (0815.08) — в archive/platform-PROGRESS-P4-P6.md; вынесено 16.08 по слову владельца.)

Эра пака P7 (1620.08) — в архиве

Пять актов, приёмка, фикс-раунды и таблицы селф-ревью выселены срезом в archive/platform-PROGRESS-P7.md (норма: закрытая эра не живёт в журнале). Итог и то, что пережило пак, — шапка выше и пинг оркестратора №18 ниже.

Закрытые эры P0P3 — в архиве

Разделы сессий P0P3 и их ратификаций (0408.08) вынесены в archive/platform-PROGRESS-P0-P3.md (D39.124). Решения оттуда живут в D-логе и DEFECT_REGISTER.md.

Пинги оркестратора (живые ссылки для следующих сессий)

Пинг оркестратора №15 (09.08, D39.122): движковый пак «блокеры контракта» ПРИНЯТ и заленден 0e69bc1 — пять поверхностей для платформы существуют. ФИНАЛЬНЫЕ формы (менялись трижды за приёмку — старые в переписке игнорировать):

  • Манифест глав: <project_db>.manifest.json, manifest_version: "tm-manifest-v2" (v1 движок сам отклоняет); id главы = 16 hex (стабилен через пере-нарезку); unit.id = <chapterID>:<cutTag>:<firstChunkIdx> — тег разреза 8 hex, при любой смене нарезки/данных пары unit.id УМИРАЮТ намеренно (id жив ⇒ якорь цел); поле heading — ВРЕМЕННЫЙ рендер движка «Глава N», НЕ метка книги (решение владельца 09.08; настоящие заголовки — строка 160 бэклога движка). $0-команда tmctl manifest строит дерево до первого прогона (первое касание создаёт БД проекта — то же поведение, что у status).
  • Прогресс: status --jsonprogress: {draft:{done,total}, edit:{done,total}} на книге и в каждом элементе chapters; done = «разрешено волной» (ok/flagged/skipped); волна, которой нет, — total: 0; процент не отгружается — собирает клиент.
  • Банк: <project_db>.bank.json (весь банк тремя статусами; id термов — длино-префиксированный хеш ключа уникальности, стабилен через пересборку) и <project_db>.bank-stop.json (полная таблица подписи; conf: null ≠ 0). ⚠ ИСПРАВЛЕНО оркестратором №18 (20.08, линза шва P7): «ВСЕ сайдкары атомарно» — НЕВЕРНО. Атомарны (temp+Sync+rename, backend/internal/pipeline/artifact.go:24-59) ровно три — manifest.json, bank.json, bank-stop.json, — и читать во время прогона можно ИХ. bank-stop.txt, mined-signature.yaml, auto-bank.yaml пишутся os.WriteFile с усечением первым делом: читателей у них сегодня нет, и сессия, взявшая любой по прежней формулировке, получила бы усечённый документ на живом прогоне.
  • Потолок (строка 145): tmctl translate|redrive --ceiling-usd <usd> — это КНИЖНЫЙ ПОТОЛОК В СИЛЕ, не бюджет прогона (ратифицировано D39.122): леджер сравнивает значение с накопленным committed+reserved книги. Пересчёт пользовательского «прирост в главах» (D39.110) в абсолют — ОБЯЗАННОСТЬ платформы. ⚠ АМЕНДИРОВАНО D39.123 (PD-158): формула = committed_usd + прирост×оценка, БЕЗ reserved — read-only status показывает leftover-reserved, который store.Open зануляет до первой судимой резервации; включение переплачивало бы запасом сверх холда (исполнено обеими формулами против гейта). reserved_usd читается обязательным полем как гард присутствия и улика leftover. Значение ниже уже потраченного откажет первой же резервации. День-потолок не перекрывается. Опция по желанию зоны: движок готов провести --ceiling-usd и в status, чтобы мониторинг видел действующий потолок capped-прогона (сегодня status показывает книжный) — скажите, заведём строку.

Пинг оркестратора №16 — 09.08.2026 (форма DEFECT_REGISTER, строка 167)

Реестр дефектов дорос до 171 строки одной таблицей; докс-аудит D39.125 (worksheet docs/archive/reports/DOC_AUDIT_INVENTORY_2026-08-09.md, жалоба «зонная изоляция прячет половины тем») просит форму: разложить таблицу на СЕКЦИИ (open по весу · accepted-risk · fixed по эрам паков), сохранив построчную форму | PD-N | … |docs/scripts/counts.py ключуется формой строки, не позицией, секции его не ломают. Заведите П-строкой в свой BACKLOG, исполнение — попутно следующим паком, НЕ срочно. Вопросы — через владельца.

Пинг оркестратора №17 — 15.08.2026 (migrate принят, D39.134 — движковая половина самолечения ФИНАЛЬНА)

Бэкенд-пак tmctl migrate принят и заленден (d55edd4): exit 13 = schema_mismatch финализирован, токен schema_mismatch found=N expected=M на stderr стабилен, write-путь тоже отказывает БД новее бинаря. Ваш PD-201 (самолечение «поймал 13 → migrate → повтор») теперь можно строить — движок больше не сдвинется под ногами; строку реестра, ссылающуюся на «движкового migrate ещё нет», обновите. Хвосты вашей зоны, найденные приёмкой (вход промта P7, исполнение попутно): (1) deploy/README.md:131 цитирует МЁРТВЫЙ текст ошибки схемы («schema vN … expects vM») — движок его больше не печатает; (2) та же мёртвая цитата и уплывший якорь store.go:135-143 в строке П-1 вашего BACKLOG; (3) комментарий-образец в tmplatformctl (runs.go:45) зовёт голый tmctl из PATH — копипаст воспроизводит тихий no-op СТАРЫМ бинарём при живом деадлоке, ваш же README:139-141 требует версионированный путь. Вопросы — через владельца.

Пинг оркестратора №17 (второй) — 15.08.2026 (S4 принят, контракт 0.2.3 в каноне — пять строк вашего регистра протухли; аудит корпуса)

Фронт S4 принят и заленден (D39.135), контракт 0.2.3 в каноне. Для вашего регистра: (1) PD-172 · PD-173 · PD-174 · PD-180 — диспозиция «спек-правка 0.2.3 задачей S4» (D39.130 п.2в) ИСПОЛНЕНА — правила стоят в openapi.yaml §createBook (PD-172 при этом уточнён ПО ВАШЕМУ коду: чтение останавливается на файле, обязательное после файла = 400 «как не слали», необязательное молча теряется — D39.135 п.2б); обновите статусы. (2) PD-199 ратифицирован закрытым ещё D39.132 п.2а («null на проводе подтверждён»), в регистре до сих пор open — привести. (3) Ваше НОВОЕ обязательство в P7 (D39.135 п.2в): читать BookIntake.title (сегодня падает в «unknown field is IGNORED», v0.go:369-376) и проецировать books.reject_reason на провод (сегодня «kept for an operator and never projected», v0.go:497) — без этого 0.2.3 остаётся обещанием без носителя. (4) Кандидаты в P7 по аудиту корпуса 15.08: PD-219 (упавший дрейн теряет хвост unit_resolutions навсегда — зона сама вешала его на читающую поверхность) · PD-217 (книга на вечном холде блокирует апгрейд движка — вторая половина после D39.132) · PD-162 (удалённый каталог книги = вечный прогон с открытым холдом). (5) ⚠ Ваш же журнал честно фиксирует: «tmctl migrate живьём не гонялся» — команда теперь СУЩЕСТВУЕТ и принята (D39.134); мнение оркестратора: прогнать деплой-рантбук end-to-end на дев-стенде настоящим migrate — обязательное предусловие первого выката, дешевле любого пака. Вопросы — через владельца.

Пинг оркестратора №17 (третий) — 16.08.2026 (контракт-ревью принято D39.138: ваша половина батча 0.3.0, PD-104 закрыт, попутные находки)

Контракт-ревью API v0 отработало отдельной сессией и ПРИНЯТО (отчёт — docs/research/28-contract-review.md; решения владельца — его §8, ратификация D39.138). ⚠ Читать ОРИГИНАЛ отчёта, не этот пересказ — он и есть носитель.

  1. PD-104 ЗАКРЫТ словом владельца 16.08 (§8 п.14): SignupGrantMicroUSD0 на бете, начисление руками; возврат $5 — вместе с суточным агрегатным потолком, когда появятся платежи. Исполнение — P7-однострочник конфига + тест (грант при неверифицированном email уже 0, login.go:306-308). Обновите регистр.
  2. Ваша половина батча 0.3.0 — ПОСЛЕ лендинга спеки; состав — §5 отчёта: wireProgress → один счётчик (Б-0; ваши колонки и словарь шва НЕ трогаются — фазы остаются внутренним делом); словарь машинных code + request_id в Problem (Б-1/§8а: класс 1 — конкретика максимальная, класс 2 модельный — ОДИН грубый код без вариации); GET /capabilities (Б-2: пары/порог интейка/форматы/страницы/версия — всё уже есть в конфиге и константах); WWW-Authenticate на 401 и две причины 403 (Б-15); трейлинг-части интейка → 400 вместо тихой потери + Location на 201 + Idempotency-Key (Б-3); подрезание limit до максимума вместо сброса к дефолту (Б-10, books.go:509-511); PATCH /books/{id} title-only + DELETE + GET /runs/{id} + Run.failure_reason (Б-5/Б-8 — словарь исхода у движка уже есть); blocked: {code, book_id} на run-options/409 (В-6); отказ по неподдерживаемой паре кодом на интейке (сегодня ja/en-книга умирает failed-ом на валидации конфига движка в КОНЦЕ пути — денег не сгорает, но причина не доезжает).
  3. Сеть (§5б; вход до первой живой книги под фронтом, строка 186): gzip на текстовых ответах (НЕ на SSE) и ETag/If-None-Match→304 на списочных GET — ваше же требование PLATFORM_DIRECTION.md:202-205, батчем оно уезжает В КОНТРАКТ. Числа: дерево 2283 глав = 250 КБ на кадр status, фокус-рефетч 12 вкладок = 562 КБ.
  4. К-10 (пофазность у главы): НЕ СТРОИТЬ — поправка приёмки: вердикт §6 отчёта («правка проекции») противоречит Б-0; фазы уходят с провода и у главы.
  5. Попутные находки §9 (сессия их адверсариально НЕ судила — проверьте у себя, заведите П/PD-строки по месту): (а) расчёт может висеть навсегда в двух легаси-путях (reconcile.go:660-670 — попытка без базовой отметки; дев-путь без движка) — бюджета «сколько холд может висеть» не существует; (б) флаг «аккаунт остановлен» выводится сканом последних прогонов ВСЕХ книг (pgstore/books.go:720-724) — одна книга зажигает аккаунт; после PD-203 перечитать; (в) ReadRunForSpawn линеен по живым прогонам (pgstore/runs.go:712); (г) /metrics без аутентификации, защита — только 127.0.0.1 (main.go:200-202); (д) лимитер входа один на процесс (login.go:128-129,165) — один клиент упирает вход всем (выбор объяснён комментарием, следствие стоит записать); (е) сырой Go-текст ошибки лежит причиной карантина в БД (reconcile.go:320) — на провод не идёт. Вопросы — через владельца.

Аддендум к пингу №17-третьему (16.08, свип планировочных доков D39.139): (1) docs/PLATFORM_DIRECTION.md §2 и BACKLOG.md П-7 держат «фри-тир дефолт $5» — ПРОТУХЛО против PD-104 (слово владельца 16.08: грант 0 на бете, начисление руками; D39.138 п.2л) — поправить тексты при P7. (2) Баннер §3 PLATFORM_DIRECTION («ратификация за оркестратором») закрыт ещё D39.132 п.2б: oapi-codegen — кандидат при P7, sqlc — привязан к P7, River-факт поправлен; баннер снять/заменить ссылкой на ноту. (3) §4 п.5 («сервер ВПРАВЕ склеивать события») сузится батчем 0.3.0: склейка только снимкам, note не склеивать (research/28 Б-6в). Вопросы — через владельца.

Дозакладка к §4.6 промта P7 (16.08, аудит готовности зоны; релей владельца — подтверди эхом): к списку протухших текстов зоны добавь: PLATFORM_DIRECTION.md §4 п.8 («живого канала до-прогонных состояний нет») — решено книжным SSE 0.3.0, опрос запрещён нормой · §4 п.10 («персист манифеста — недостающий») — построен D39.122 · :184 ссылка на несуществующий §3.3 стандартов · platform/README.md:3-4 шапка «зона на P1» и «один тест-гейт» (гейта два) · BACKLOG.md П-17 — состав пака у́же промта (промт первичен). Расхождение ENGINEERING_STANDARDS:59 против DIRECTION:128 по oapi-codegen решаешь ты (промт §4.6). Всё — попутно, не отдельным заходом.

Пинг оркестратора №18 — 20.08.2026 (P7 акт 5 ПРИНЯТ С ФИКС-ЛИСТОМ и ЗАЛЕНДЕН; контракт 0.4.0 ратифицирован; тело — D39.152/D39.153)

Вердикт: ПРИНЯТЬ С ФИКС-ЛИСТОМ. Панель шести линз в изолированных копиях (слепая · контракт-конформность · деньги · шов · вне карты · ревью канона 0.4.0 другой моделью) + пере-раны и собственные посадки оркестратора. Регрессов против HEAD нет, ни одной линзы с REJECT.

Пере-проверено МОЕЙ рукой (заявление = команда): make check с обоими гейтами — 18 пакетов, EXIT=0, скипов 0, линтер 0 issues · реестр 327 строк / 65 открытых (13 minor, 52 info), major и BLOCKER нет — python3 docs/scripts/counts.py --check · оба док-гейта зелёные · tmplatformctl books --migratable живой (exit 0, «resumable run» на стендовой книге) · миграционный манифест сходится, released-миграции не тронуты, комментарий про пере-отпечаток 00016 честный.

Замер, обосновавший разворот 00016→00022, пере-выведен независимо (свой бенчмарк на трёх вариантах в копии дерева): джойн 14.6 мс · счётчик 5.3 мс · без счётчика 2.9 мс. Порядок и вывод подтверждаются, разворот законен. ⚠ Процент назван в ТРЁХ носителях тремя разными числами (журнал «83%», perf_test.go:13 «96%», миграция 00022 «16.8 против 3.4, джойн сам по себе 9 мс»); мой замер даёт ≈80%, а «96%» ни из чего не выводится — один носитель на факт, остальные указывают.

Собственные посадки мутаций ВНЕ вашего списка — 8, поймано 7: долг не поставлен третьей концовкой · edit_wave не монотонен (⚠ сообщение пина печатает указатель вместо значения — readmodel_test.go:918) · снят Vary: Accept-Encoding · HEAD лишён валидатора · reopen снимает стоп банка кому угодно · погашение долга без сверки метки · вынос метки долга из закрывающей транзакции во второй оператор (техника xmin §36 работает, проверено исполнением).

НЕ поймано — дыра: снятие structure_version И revision из emitFrame (pgstore/events.go:72-73) проходит ВСЮ батарею. Это два поля, которые канон требует на КАЖДОМ кадре (EventBase), и ваш же комментарий это утверждает. По вашей норме PD-1 свойство без пинящего теста считается НЕ закрытым.

Фикс-лист приёмки — завести строками СВОЕГО бэклога и регистра (зона моя не пишет)

ПЕРВЫМ — не из пака P7, но найдено вторым рубежом приёмки и проверено мной построчно: Sweep останавливается для ВСЕЙ инсталляции на двух медленных прогонах, и выхода нет. cmd/tmplatformd/runner.go:189sweepBudget = 2 * time.Minute на ВЕСЬ проход; internal/runs/reconcile.go:70defaultRunBudget = 60 * time.Second на ОДИН прогон. 120/60 = 2: два прогона, выбравшие свой бюджет, съедают проход целиком, и тогда ctx.Err() (reconcile.go:39,48) обрывает цикл — UnsettledRuns, единственный ретрай отложенного расчёта, не вызывается вообще, а живые прогоны, стоящие ниже, не реконсилируются и не спавнятся. ListLiveRuns сортирует order by r.started_at (pgstore/runs.go:249), то есть заклиненный прогон — по построению самый старый — стоит в голове и голодит остальных КАЖДЫЙ проход, детерминированно. Ручки нет: runs.Config.RunBudget объявлен (internal/runs/runs.go:62-65), но startRunner его НЕ присваивает (cmd/tmplatformd/runner.go:74-83), переменной окружения нет ни для одного из двух чисел, а tmplatformctl не умеет ни закрыть прогон, ни вернуть холд. Цена: прогон вечно finished_at is null ⇒ холд не возвращается ⇒ runs_one_live_per_book не даёт запустить новый прогон этой книги. Деньги заморожены, книга заморожена, пользователю видно «идёт». Достижимо буднично, без экзотики: RunSink.Apply берёт транзакцию с блокировкой книги на КАЖДУЮ строку журнала (pgstore/sink.go:80-104), поэтому после часа простоя демона две книги с бэклогом выбирают проход целиком — и всё время догона деньги всей инсталляции не считаются. ⚠ PD-169 в вашем регистре стоит fixed(P5) и этим ЛЖЁТ приёмке: его пин гоняет Sweep вообще без дедлайна прохода, то есть доказывает пер-прогонный бюджет, а не выживание прохода. Пере-открыть. Код приехал в P6 и в дифф P7 не входил (Sweep против HEAD — identical), поэтому ни одна диффовая линза его увидеть не могла: тот же класс «композиция известных фактов», что и строка 198. ⚠ Наблюдаемость при этом ЕСТЬ и она ваша: tm_platform_sweep_unfinished_total растёт — то есть оператор увидит, что проход не дошёл до конца, и не сможет ничего сделать. Метрика без ручки — половина механизма.

  1. ContractVersion = "0.3.0" при формах 0.4.0 (internal/httpapi/capabilities.go:13, он же в каждом hellostream.go:100). Ратификация 0.4.0 состоялась (D39.152) ⇒ константа обязана подняться. Комментарий над ней сам это требует: «raised in the same commit as the code that implements a new minor». Сегодня практического вреда нет (фронт заморожен на 0.2.3), но деплой объявляет версию, которую не отдаёт. Первым пунктом.

  2. Пины на два поля EventBase (см. выше). ⚠ Попутно 21.08 усилен гейт якорей доков: file:line теперь может нести токен ожидания (`путь:12-14`=`подстрока`), и такой якорь сверяется ПО СОДЕРЖИМОМУ на каждом прогоне, включая коммиты, которые двигают ЦЕЛЬ. Ваши доки (platform/docs/**) вошли в область линта — раньше их не сканировал никто.

  3. Бюджет попыток материализации. У долга нет предела и канала «признать безнадёжным»: claim → fail → defer(now()) → следующий свип через 15 с, вечно (pgstore/books.go:538,557-564). У интейка предел есть (parseAttempts=5). Три следствия: до 5 мин движковых процессов на проход бесконечно · поток такой книги НЕ заканчивается никогда (AtRest требует read_model_owed_at is null, events.go:125) · при живом манифесте и падающем экспорте SaveStructure коммитится каждый проход ⇒ revision++ и кадр каждые 15 с.

  4. sqlc — БЕРЁМ, слово владельца 20.08 («я вообще за»). Отступление P7 закрыто, PD-44 переоткрыть исполнением. ⚠ Ваше предложение «взять на однооператорных ручках P8» покупает инструмент туда, где не болит: рантайм-ошибки «нет такой колонки» случились в СКЛЕЕННОМ SQL read-модели (⚠ счёт: проверяемый носитель — ваш регистр PD-44 и журнал — несёт ДВЕ; ещё две вы назвали в ответе владельцу, в доки они не попали, поэтому опираемся на две — испр. 20.08) (chapters_before/stop_for_signingreadmodel.go:441,446, там же note_count и сломанный алиас b), куда sqlc по построению не дойдёт. Тем же паком — гейт, который туда дойдёт: прогонять КАЖДЫЙ собранный запрос через разбор Postgres (prepare/describe) против мигрированной схемы; склейка ему не мешает, он получает финальную строку. И ответить попутно на вопрос, которого мы не знаем: есть ли в read-модели запрос, которого не касается ни один тест — если есть, это не «медленная обратная связь», а дыра. ⚠ Половина ответа УЖЕ получена вторым рубежом приёмки (собранный SQL извлечён из пакета через go/types и прогнан EXPLAIN (GENERIC_PLAN) против мигрированной схемы): 141 запрос, все планируются чисто, остаточных «нет такой колонки» НЕТ; тестом ЭТОГО пакета недостижимы десять, но по батарее ЦЕЛИКОМ реально не покрыты только три (DeleteOldLoginEvents · UserByIdentity · Observe; остальные семь покрыты на 5887% тестами соседних пакетов — пере-мерено покрытием при аудите 20.08, первая редакция называла десять и это было неверно) — RefundParseAttempt · StuckIntake · OpenReservations · ReleaseUnspawned · DeleteOldLoginEvents · UserByIdentity · Observe · SpendBound · AttemptReservationOpen · RunPausedReason, и ни один из них не трогает схему 0001600024. То есть дыры сегодня нет, а гейт нужен как ПОСТОЯННЫЙ — именно он и делает этот ответ воспроизводимым.

  5. PD-297 — round-trip на строку в SaveStructure под эксклюзивной блокировкой книги; мерить на корпусной книге до и после (корпусная книга появится на холодном прогоне движка).

  6. Труба доставки решений банка в движок — единый бэклог, строка 199(а): перед resume писать решения в mined_delta/mined_rejects. Сегодня action/dst — write-only колонки (единственный SELECT readmodel.go:336 проверяет лишь наличие строки), а воркер описан в комментарии вашей же миграции 00002_readmodel.sql:172-174 и не построен.

  7. Мусор: пустой platform/ru (0 байт, обрубок редиректа) — в лендинг не взят, снесён оркестратором. books.go:234-235 — задвоенная первая строка доккомментария, класс PD-310/326.

  8. Ревью-пак четырёх осей, которых не смотрел НИКТО (ваш же obstacle): деньги и леджер целиком · вход/сессии/CSRF · очередь и джобы · метрики. Это не дофикс и не довесок — первый взгляд, отдельной работой.

  9. Один носитель на факт для замера 00016→00022 — но НЕ удалением числа. Выигрыш назван ЧЕТЫРЬМЯ носителями: шапка этого журнала «83%» · internal/pgstore/perf_test.go:13=96% of the page «96%» · миграция 00022 «16.8 против 3.4, джойн сам 9 мс» · регистр PD-306 (повторяет 83% и 16.8/3.4). ⚠ Я сперва записал, что «96%» ни из чего не выводится — это была моя ошибка, снята проверкой записей: оно выводится точно из ВАШЕГО же замера в archive/P7_ACT5_FIX_PLAN_2026-08-20.md:444-446=636 мс против («636 мс против 24 мс», холодный корпус акта 4) = 96.2%, тогда как 83% и мой независимый ≈80% — с вакуумированного корпуса. То есть носители меряли РАЗНОЕ и все честны. Свести указанием УСЛОВИЙ замера при каждом числе, оставив нормативным один (миграция 00022 — она их и несёт); удалять «96%» как фантом НЕЛЬЗЯ.

  10. У материализатора нет ПОЛА на пустой манифест — латентная потеря всего текста книги. internal/readmodel/readmodel.go:215-232 строит in.Chapters только из manifest.Chapters и ни разу не сверяется со счётчиками того же документа (ChaptersTotal/UnitsTotal лежат рядом и печатаются в лог строкой ниже). Пустой список едет в SaveStructure, где pgstore/readmodel.go:193-196 выполняет delete from chapters where book_id = $1 and not (id = any($2)) — на пустом массиве предикат истинен для ВСЕХ глав, и каскад chapters → units сносит текст; при пустом Key вдобавок срабатывает changed и уходят все unit_resolutions (родня строки 198). Сегодняшним движком недостижимо (buildManifest всегда наполняет главы, файл пишется атомарно) ⇒ фикс-лист, не блокер. Асимметрия и есть находка: на ИНТЕЙКЕ ровно этот случай отловлен явно и прибит мутацией (internal/books/parse.go:134-142, books_test.go:1296) — «нет глав, но работа считается» там не признаётся правдой о книге. У материализатора такого пола нет, и теста на нулевой манифест в readmodel_test.go тоже нет. Лечится одной сверкой len(manifest.Chapters) против manifest.ChaptersTotal.

  11. PD-327 в регистре стоит open, а канон 0.4.0 РАТИФИЦИРОВАН (D39.152) — то есть условие её закрытия наступило. Закрыть строку регистра явно; сегодня расхождение видно скриптом (counts.py --check печатает PD-327 среди открытых), и это ровно тот класс, ради которого регистр объявлен источником истины по статусу.

  12. Изоляция читающих чтений НЕ ЗАПИНЕНА (аудит 21.08, посадка мутации). Снятие RepeatableRead+ReadOnly у inReadTx (internal/pgstore/credits.go:492-493) проходит ВСЮ батарею — при том, что под этим инвариантом лежат шесть ручек выдачи, а носитель прямо объясняет цену («every frame in that window was lost for good», books.go:684-688, PD-163). По вашей же норме PD-1 свойство без пинящего теста считается НЕ закрытым — а это тот самый класс, которым я мерил найденную дыру с emitFrame. Код приехал НОВЫМ в P7, то есть лежал внутри диффа, который читали шесть линз приёмки и я сам.

  13. CreditHeldBy: оговорка and book_id <> $2 не запинена (аудит 21.08, посадка мутации). Мутант, снимающий её, проходит батарею: пин, который выглядит покрывающим, её ни разу не исполняет — в фикстуре у исключаемой книги холда НЕТ (internal/pgstore/credits_test.go:443-465). Сумма кормит контрактный blocked, и раздутая сумма отправляет пользователя гасить прогон, который ничего не освободит — ровно тот вред, против которого написан комментарий над самим запросом (credits.go:393-397).

Что ушло в ЕДИНЫЙ бэклог (движок/шов/контракт — ваши строки туда не заходят, D39.84)

198 апгрейд движка стирает замечания и счётчики безвозвратно (ваша зачистка при ре-кате × announce-once движка — композиция, гейт холодного прогона) · 199 канал доставки правок банка · 200 сквозная полоса прогресса вместо пофазной (слово владельца 20.08) · 201 «Глава N» внутри текста экспорта · 202 живой прогон насквозь через API — ПОСЛЕ холодного прогона движка (слово владельца 20.08) · 203 хвосты контракта · 204 движок публикует причины флагов данными (релей §7в, ваш PD-246 — строка заведена в бэклоге ДВИЖКА, как вы и просили). ⚠ По релеям §7 сверено грепом при лендинге, а не по вашему списку: (б) и (д) уже ИСПОЛНЕНЫ синком 0.4.0, (г) наполовину (unspecified ратифицирован, открыта граница ступеней), (и) закрыт полем stop_requested. Реально открыты только (а)-канон-половина, (з) и договорная часть (к).

Ратификации, которые вас касаются

Контракт 0.4.0 РАТИФИЦИРОВАН (D39.152) — PD-327 закрывается лендингом канона, он состоялся. ⚠ Ваш клейм «ломающая правка ровно одна» верен для диффа генерённых ТИПОВ и неточен поведенчески: против 0.3.0 расходятся ПЯТЬ мест — пятое, семантика 410 Gone, принесена проверкой записей и названа вашим же PD-253 (stop_requested · тождество интейка по содержимому против дословного «never over the bytes themselves» · 409 там, где таблица резюма говорит 202 · валидатор на двух ручках сверх объявленных). Все четыре 0.4.0 благословляет, поэтому цена уплачена ратификацией — но клейм в отчёте стоит поправить, чтобы следующая приёмка не опёрлась на него.

Оговорка про пер-термные решения расширена на ВСЮ ручку (была только на decline): инертны одинаково и approve, и dst. Оговорка временная — снимается исполнением строки 199(а).

Исправление МОЕГО же пинга №15 (испр. оркестратором №18): «Все сайдкары пишутся атомарно (temp+rename)» — НЕВЕРНО. Атомарны три из шести (manifest.json, bank.json, bank-stop.jsonbackend/internal/pipeline/artifact.go:24-59); bank-stop.txt, mined-signature.yaml, auto-bank.yaml пишутся os.WriteFile с усечением. Сегодня безвредно (читателей нет), но сессия, взявшая любой из них по той строке, получит усечённый документ на живом прогоне.

Сессия P7 ЗАКРЫТА владельцем 20.08. Промт отработан → platform/docs/archive/. Дальше — другие сессии.