diff --git a/docs/BACKEND_WIREBATCH_SESSION_PROMPT.md b/docs/BACKEND_WIREBATCH_SESSION_PROMPT.md index 2639cc31..e3fae4b9 100644 --- a/docs/BACKEND_WIREBATCH_SESSION_PROMPT.md +++ b/docs/BACKEND_WIREBATCH_SESSION_PROMPT.md @@ -24,8 +24,10 @@ 1. `backend/README.md` — устройство движка · `docs/architecture/12-go-style-notes.md` — норматив. 2. `docs/PROGRESS.md`: CURRENT-STATE и строки бэклога **210 · 46 · 113 · 134 · 140 · 184 · 197 · 198 · 204** (греп по номеру в таблице). -3. `docs/NEXT_PACKS_PLAN.md` §1 — состав этого пака и что намеренно НЕ берётся. Читать целиком: там - разобрано, почему пункты собраны вместе и какие две строки батч задевает сам. +3. **Состав и его доводы — здесь, в этом файле.** Разбор «почему пункты собраны вместе и что + намеренно НЕ берётся» лежит в отработавшем плане `docs/archive/reports/NEXT_PACKS_PLAN_2026-09-03.md` + §1 — ⚠ это АРХИВ: читать как ДОВОД, инструкции оттуда не исполняются, приказ несёт этот промт. + Ратифицированные решения по очереди — нота **D39.190** (грепом по номеру). 4. Журнал решений, номера грепом (`grep -n '^## D39.NNN'`): **D39.21** (род должен доезжать) · **D39.93** (форма экрана цели) · **D39.104** (банк на проводе — закон) · **D39.105/D39.108** (доктрина заголовков и павший гейт) · **D39.147** п.2в (140 — стройка, не развилка) · diff --git a/docs/PLATFORM_EXPORT_SESSION_PROMPT.md b/docs/PLATFORM_EXPORT_SESSION_PROMPT.md index 27e9b245..01f3d403 100644 --- a/docs/PLATFORM_EXPORT_SESSION_PROMPT.md +++ b/docs/PLATFORM_EXPORT_SESSION_PROMPT.md @@ -26,8 +26,10 @@ 1. `platform/README.md` — устройство зоны · `platform/docs/ENGINEERING_STANDARDS.md` (обязателен). 2. `platform/docs/platform-PROGRESS.md` — зонный журнал: пинги оркестратора и отчёты паков P12/P13. -3. `docs/NEXT_PACKS_PLAN.md` §2 — состав этого пака, что намеренно не берётся, и разбор механизма - потолка. Читать целиком. +3. **Состав и его доводы — здесь.** Разбор лежит в отработавшем плане + `docs/archive/reports/NEXT_PACKS_PLAN_2026-09-03.md` §2 — ⚠ АРХИВ: читать как ДОВОД, инструкции + оттуда не исполняются. Механизм потолка ратифицирован **эрратой 04.09-а к D39.189**, решения + очереди — **D39.190**; оба грепом по номеру. 4. `docs/architecture/14-api-contract/` — канон; **зеркало фронта НЕ норматив**. Ряды регистра по номеру: `PD-424` · `PD-418` · `PD-438` · `PD-217` · `PD-246`. 5. Журнал решений грепом: **D39.189** и **эррата 04.09-а к нему** (механизм потолка) · **D39.176** п.3 diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 98f4fda0..fba36d80 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -17,7 +17,7 @@ **Залендены и ратифицированы, приёмочные дампы — телами нот:** платформенный **P11** — D39.169 · движковый пак **«деньги»** — D39.170 · платформенный **P12** — D39.180 (вместе с контрактным минором **0.9.0**; `PD-425` закрыт им же) · бэкенд-пак **«деньги и честность выдачи»** — D39.182 (тестов 1045→1083, удалённых ноль) · **закон раскрытия** движка — D39.181, ратифицирован владельцем и применён к одиннадцати экземплярам. **ВЫДАНЫ 04.09 и РАБОТАЮТ ПАРАЛЛЕЛЬНО** (зоны независимы по коду; сцепление одно — **форма манифеста ЗАМОРОЖЕНА на время окна**, чтобы бамп не сорвал платный прогон платформы, `D39.190` п.5): бэкенд — вайр-батч `docs/BACKEND_WIREBATCH_SESSION_PROMPT.md`; платформа — «закрыть цикл» `docs/PLATFORM_EXPORT_SESSION_PROMPT.md`. ⚠ Строка **160** взята, но идёт СВОИМ паком ПОСЛЕ двери: она бампает `manifestVersion`, у которого безопасного порядка деплоя нет (`D39.190` п.2). Строка **142** — после шагов 0–1 полигона (`D39.190` п.3). -> **Предыдущие паки ОТРАБОТАНЫ 03.09, ПРИНЯТЫ С ДОФИКСОМ и заленджены** (`D39.187` движок, `D39.188` платформа; промты в `archive/prompts/` с баннерами исхода; следующие паки ПЛАНИРУЮТСЯ — `NEXT_PACKS_PLAN.md`, промты не выданы до обоюдного «ок» оркестратора и контролёра, слово владельца 03.09): платформенный **P13** «шов возврата оплаченного прогона» (`docs/PLATFORM_P13_SESSION_PROMPT.md`: `PD-168` бюджет из холда · `PD-89` ключ на пути ошибки · `PD-426`/`PD-214` чужая строка не карантинит проекцию · `PD-374` гейт батареи · гейт против класса серьёзности · строка рантбука деплоя) и бэкендовый **«число согласия на пути второй покупки»** (`docs/BACKEND_CONSENT_SESSION_PROMPT.md`: ФЧ-5 ось модели · строка 232 остаток слота · ФЧ-4 обе половины · ФЧ-1 три гарантии). ⚠ **Сцепление по деплою названо в обоих: у формы манифеста БЕЗОПАСНОГО ПОРЯДКА НЕТ** — гейт интейка `platform/internal/ingest/manifest.go:112`=`if m.Version != KnownManifestVersion` сравнивает со строгим равенством одной константе, окна двух версий нет; рантбук `platform/deploy/README.md:217`=`сначала платформа, потом движок` советует обратное и отдан на починку паку P13 пунктом 6. +> **Предыдущие паки ОТРАБОТАНЫ 03.09, ПРИНЯТЫ С ДОФИКСОМ и заленджены** (`D39.187` движок, `D39.188` платформа; промты в `archive/prompts/` с баннерами исхода; план паков отработал и ушёл в `archive/reports/NEXT_PACKS_PLAN_2026-09-03.md`; решения — D39.190, промты ВЫДАНЫ 04.09): платформенный **P13** «шов возврата оплаченного прогона» (`docs/PLATFORM_P13_SESSION_PROMPT.md`: `PD-168` бюджет из холда · `PD-89` ключ на пути ошибки · `PD-426`/`PD-214` чужая строка не карантинит проекцию · `PD-374` гейт батареи · гейт против класса серьёзности · строка рантбука деплоя) и бэкендовый **«число согласия на пути второй покупки»** (`docs/BACKEND_CONSENT_SESSION_PROMPT.md`: ФЧ-5 ось модели · строка 232 остаток слота · ФЧ-4 обе половины · ФЧ-1 три гарантии). ⚠ **Сцепление по деплою названо в обоих: у формы манифеста БЕЗОПАСНОГО ПОРЯДКА НЕТ** — гейт интейка `platform/internal/ingest/manifest.go:112`=`if m.Version != KnownManifestVersion` сравнивает со строгим равенством одной константе, окна двух версий нет; рантбук `platform/deploy/README.md:217`=`сначала платформа, потом движок` советует обратное и отдан на починку паку P13 пунктом 6. ⛔ **Проводка `--max-units` в платформу остаётся ГЕЙЧЕНОЙ. Живое основание одно и оно механическое:** единственный писатель `bank_moved_at` — дверь правок банка (`platform/internal/runs/bank.go:182`), а рост АВТО-банка от майнинга этого флага не ставит, поэтому майнящая книга на второй покупке идёт без `--resnapshot` и умирает на снапшот-гарде движка — холд взят, попытка сожжена (`PD-422`). Это чинится проводкой признака движения банка от майнинга, а не решением владельца. @@ -142,7 +142,7 @@ | 170 | **`tmctl init` — движок сам заводит книгу** (форма В развилки интейка): платформа зовёт $0-команду, движок пишет СВОЙ `book.yaml` — требования к полям живут там же, где проверяются (`config/book.go`); до неё бета живёт формой Б (рендер из деплой-шаблона платформой при создании книги, ратификация D39.130) | бэкенд | когда-нибудь (после беты формы Б) | малый пак | приёмка P5, **D39.130** | | 172 | **Остаток после пере-пина DeepSeek (пин ИСПОЛНЕН и ПРИНЯТ — D39.137, `76049bb`):** (а) **схемное решение владельца по time-based** — доклад §5 отчёта вендор-сессии (рекомендация: пик оставить; scheduler-вариант строки 60 не начинать до ответа вендора «по какой отметке времени тарифицируется вызов» — вендором НЕ задокументировано — и замера доли пика; дешёвый рычаг: операционное правило «прогоны не стартуют в 01–04/06–10 UTC» — почти всё ×2 без строчки Go; гибрид «резерв пиком, сеттл по окну факта» назван) · (б) пере-калибровка ставки $0.03/глава (166/П-10; множитель счёта замерен) · (в) exp08 v3 (85) обязателен до budget_usd · (г) **вахта весов V4-Pro-0813** (класс D39.61): риг готов, порог ратифицированной ВЫБОРОЧНОЙ формы («≥4/5 прогонов N=5 достигают 6/6», D39.136 п.6б) **в риге ИСПОЛНЕН** паком честности — арифметика вынесена в `live_reprobe_threshold_test.go`, сам риг применяет её же. ⚠ **ИМЯ СТРОКИ ВВОДИТ В ЗАБЛУЖДЕНИЕ (испр. №18 17.08, сверено кодом):** названный риг меряет роль КЛАССИФИКАТОРА, а она ходит на **flash** (стендовый `pipeline.yaml:64` + артефакт прошлого прогона `model = deepseek-v4-flash`), тогда как сменившиеся веса — у **pro**, а pro у нас = РЕДАКТОР (`configs/pipeline-c1.yaml:62,76`). Владелец 17.08 санкционировал ТОЛЬКО вариант (а) — пере-съём классификаторного гейта, потолок $0.20, исполняется п.5 пака честности. **По этому прогону строку НЕ закрывать:** вопрос «сменились ли веса редактора» остаётся открытым, дешёвый вход к нему — данные фазы Д, где pro гоняется именно редактором (спросить полигон прежде, чем покупать новый замер) | владелец → бэкенд/полигон | скоро (схема — на владельце; вахта — после 16.08) | СТОП-решение (схема) + замер (вахта) | вендор 13.08, **D39.137**, строка 60, D30.4 | | 180 | **`prices_checked` — одно поле на ВСЮ таблицу цен** (находка вендор-сессии, D39.137): бамп по факт-чеку одного вендора сдвинул 120-дневный гейт свежести остальным семи моделям (дедлайн уехал ~07.11→~13.12); лечение — пер-модельная дата проверки (правка схемы) ЛИБО ре-чек остальных вендоров отдельным заходом до исходного дедлайна | бэкенд | когда-нибудь (ре-чек вендоров — до ~07.11) | малое касание / вендор-заход | D39.137, отчёт §7.1 | -| 182 | **Wire-батч перед добором идеала — КОПИТЬ и вносить ОДНИМ касанием** (каждая правка двигает RequestHash / `memory_version` / снапшот = перекупка волн; дриблить по одной = платить пере-снапшот несколько раз): 46 экран цели (+предпосылка 113 фикстура) · 134 инжект-заголовки (гейт пал D39.108) · 131 кап инъекции · 140 банковый контур в shipping (СТОП-решение) · 105(а) вердикт-половина классификатора · 130-остаток (мердж авто-банка, гейт WARN второго прогона) · 14 ё-фолд (носитель «следующий пак общности») · **119+124(+115 пер-парный хеш EmbeddedVersion) — ОДНИМ дизайн-паком** (строка 124 требует принимать целиком; сверено кодом: `cutTag` фолдит `chunkerVersion`/`EmbeddedVersion`/`NormVersion` — `manifest.go:160-169`); вне батча свободен только 118 (tools/go.mod). Состав — аудит корпуса 15.08 (archive/reports/CORPUS_AUDIT_2026-08-15.md §В.г) | оркестратор → бэкенд | скоро (собрать к ратификации фазы Д; вносить перед первым платным прогоном добора идеала) | координационная строка → промт(ы) батча | аудит 15.08, D39.134/136/137 | +| 182 | **Wire-батч перед добором идеала — КОПИТЬ и вносить ОДНИМ касанием** (каждая правка двигает RequestHash / `memory_version` / снапшот = перекупка волн; дриблить по одной = платить пере-снапшот несколько раз): 46 экран цели (+предпосылка 113 фикстура) · 134 инжект-заголовки (гейт пал D39.108) · 131 кап инъекции · 140 банковый контур в shipping (СТОП-решение) · 105(а) вердикт-половина классификатора · 130-остаток (мердж авто-банка, гейт WARN второго прогона) · 14 ё-фолд (носитель «следующий пак общности») · **119+124(+115 пер-парный хеш EmbeddedVersion) — ОДНИМ дизайн-паком** (строка 124 требует принимать целиком; сверено кодом: `cutTag` фолдит `chunkerVersion`/`EmbeddedVersion`/`NormVersion` — `manifest.go:160-169`); вне батча свободен только 118 (tools/go.mod). Состав — аудит корпуса 15.08 (archive/reports/CORPUS_AUDIT_2026-08-15.md §В.г) | оркестратор → бэкенд | скоро (собрать к ратификации фазы Д; вносить перед первым платным прогоном добора идеала) ⚠ **СОСТАВ ОКНА 04.09 (D39.190 п.4 ратифицировал пере-снапшот единым актом):** в выданный вайр-батч вошли **210 · 113→46 · 134 · 140 · 184(а)**; СНАРУЖИ остались и это сказано вслух, а не умолчано — **131** (кап инъекции: своя цена и своё СТОП-решение, и сама строка велит «пере-замерить ПОСЛЕ 134», то есть её очередь следующая), **105(а)** и **14** (ждут следующего окна), **119+124+115** (только одним дизайн-паком), **160** (бампает `manifestVersion`, отложена ПОРЯДКОМ — D39.190 п.2), **142** (после шагов 0–1 полигона — D39.190 п.3). | координационная строка → промт(ы) батча | аудит 15.08, D39.134/136/137 | | 171 | **Число символов книги — от движка** (PD-177 платформы: `character_count` интейка точен только для UTF-8; GB18030/UTF-16 движок декодирует сам — цифра платформы на них неверна, для UTF-16 занижена ~вдвое): счёт символов в манифест (рядом `source_bytes`/`encoding`) либо перерасчёт платформой после разбора | бэкенд | когда-нибудь | малое касание (манифест) | П-13 платформы, PD-177, приёмка P5 | | 173 | **`backupStamp` секундной точности**: два `translate` в одну секунду дают коллизию имени бэкапа и exit 1, маскируя класс «проект занят» (12) — метка до наносекунд/uniquify либо распознавать коллизию явно; преexisting, вскрыт ревью эмиттер-пака | бэкенд | когда-нибудь | малое касание | приёмка D39.131 | | 175 | **Деплой движка «в полёте» — ДАЛЬНИЙ ОСТАТОК** (ближняя половина ИСПОЛНЕНА паком migrate — D39.134; правило свипа и settle запиненным бинарём — аддендум P6, D39.132). Остаток: (а) при СЛЕДУЮЩЕМ бампе схемы проставить в файл книги `application_id` + `min_reader_version` — данные-задел под окно совместимости, ~0 логики; (б) GC бинарей: удалять не пиненные ни одной незакрытой попыткой, последние 2–3 релиза держать для отката; (в) окно совместимости читателей / пин уровня книги — строить ТОЛЬКО по триггерам: много тенантов · бампы схемы еженедельно+ · потребители `status` кроме платформы. Археология захода — ресёрч 14.08 (вывод: exact-match читателей на деньгах = осознанный fail-closed, корень не выдёргивать, приделать дверь) | платформа/бэкенд | когда-нибудь (по названным триггерам; (а) — попутно первым бампом схемы) | данные-задел + малые касания | владелец 14.08, ресёрч 14.08, строка 139, D39.134 | @@ -159,7 +159,7 @@ | 192 | **Пост-ридинговый цикл правок банка — «наше подумать» владельца 16.08 (записано, чтобы не потерялось; точную механику «не продумал ещё никто и нигде» — его слово).** UX-модель целиком: юзер нажал перевод → черновая волна + майнинг вместе → на фронте появляются ЧЕРНОВОЙ перевод и ЧЕРНОВОЙ банк · подписывается ВЕСЬ банк одним ОК (D39.144) → перевод уходит в доработку · дальше юзер ЧИТАЕТ, и его опции: поправить термин в банке ЛИБО добавить свой → кнопка «поправить» → пере-генерация, которая по ВХОЖДЕНИЯМ правит запрошенное. Открытые вопросы дизайна: что именно перегенерируется (вхождения ключа · затронутые юниты · со сметой и согласием?) · нужен ли движковый ТОЧЕЧНЫЙ РЕДАКТОР (полигон над этим работает — фаза Д) · форма в контракте (ручки нет) и на экране. Уже лежит под ногами: движковый re-edit по ключу банка со сметой и $0-пере-пином ПОСТРОЕН (строка 49: `repin.go`/`rebill.go`, D39.42 п.5/D39.45) · пометка неподписанных строк · дельта-чтение банка (0.3.0). НЕ проектировать до полигонных итогов; затем дизайн-пак на их результатах → слово владельца → стройка | владелец+полигон → бэкенд/контракт/фронт | когда-нибудь (триггер: итоги фазы Д по точечному редактору) | дизайн-пак после полигона → слово владельца → стройка | слово владельца 16.08, D39.144 п.1 | | 195 | **ОСЬ «идентичность оплаченной работы» — переселена в дизайн-пак 124 (решение владельца 17.08, вариант А; D39.151).** Как САМОСТОЯТЕЛЬНАЯ стройка ЗАКРЫТА: маркер `snapshot_id`/`run_id` на `checkpoints` отдельной колонкой НЕ строится. Причина — внешний разбор опроверг посылку «колонка = тождество»: $0-пере-пин законно переносит строку на новый снапшот со СТАРОЙ ценой (`stagerun.go:96-105`, сверено оркестратором), у старых чекпоинтов бэкфилла нет вовсе (`jobs.snapshot_id` перезаписывается каждым ре-снапшотом) ⇒ вывод-обход остаётся в коде навсегда как legacy-ветка, а колонка лишь добавляет рядом второй путь. **Настоящий корень глубже:** в сторе нет первоклассной связи «строка диспозиции ↔ вызовы, которые её оплатили»; снапшот на чекпоинте — прокси, а не примитив. ⚠ Границы семьи сужены тем же разбором: 49 и 195 — про РАЗНОЕ (49 = когда переиспользование законно, 195 = как честно посчитать будущую покупку), общий у них субстрат, не задача; из 124 родня только ось (в). **Срочности нет:** под контрактом D39.150 («направление ошибки, не точность») ни один исход не занижает молча — недостача несётся историческими деньгами С РАСКРЫТИЕМ, пойманный откат называется вслух. Остаточные нарушения контракта чинятся БЕЗ схемы: 197 и 194 | бэкенд | когда-нибудь (гейт — триггеры пака 124: дописывание глав 185 · МАСШТАБ · первый внешний потребитель числа) | ось дизайн-пака 124 | **D39.151**, внешний разбор 17.08 | | 196 | **Остаточный класс строки 176: неперехватываемые `fatal error` Go** (конкурентная запись в map, OOM, стек-оверфлоу) по-прежнему дают exit 2, то есть читаются платформой как «завершено с флагами» — `recover` их не ловит по устройству языка (подтверждено линзой шва исполнением). Строка 176 закрыта для ПАНИК, не для fatal. Лечение — вне exit-контракта: сторож процесса у платформы либо маркер живости в артефакте прогона | бэкенд/платформа | когда-нибудь | отдельное решение | приёмка №18, линза шва | -| 197 | **Фикс-лист приёмки пака честности ФЧ-1…ФЧ-8** — восемь пунктов класса «заявленное не прибито» и «текст обещает больше числа», ни один не блокировал лендинг. **Тело списка дословно, с весами и с секцией «что НЕ проверено», — [archive/PROGRESS-2026-08-17.md](archive/PROGRESS-2026-08-17.md), запись приёмки №18** (D39.149). Здесь держим только ратифицированное: **ФЧ-5 РЕШЁН владельцем 17.08 (D39.150): прайсить по модели, которую стадия резолвит СЕЙЧАС, + округление вверх и оговорка в тексте согласия.** Носителя-сессии НЕТ — по слову владельца 17.08 пока только записано | бэкенд | скоро (следующее касание денежного пути; ФЧ-5 обязателен до первого пере-прогона со сменой модели) | дофикс-промт ЛИБО попутно ближайшим паком | **D39.149**, **D39.150** | +| 197 | **Фикс-лист приёмки пака честности ФЧ-1…ФЧ-8** — восемь пунктов класса «заявленное не прибито» и «текст обещает больше числа», ни один не блокировал лендинг. **Тело списка дословно, с весами и с секцией «что НЕ проверено», — [archive/PROGRESS-2026-08-17.md](archive/PROGRESS-2026-08-17.md), запись приёмки №18** (D39.149). Здесь держим только ратифицированное: **ФЧ-5 РЕШЁН владельцем 17.08 (D39.150): прайсить по модели, которую стадия резолвит СЕЙЧАС, + округление вверх и оговорка в тексте согласия.** Носителя-сессии НЕТ — по слову владельца 17.08 пока только записано | бэкенд | скоро (следующее касание денежного пути; ФЧ-5 обязателен до первого пере-прогона со сменой модели) ⚠ **СОСТАВ ПЕРЕ-СКОУПЛЕН 04.09:** ФЧ-1/ФЧ-4/ФЧ-5 закрыты паком «число согласия» (D39.187); **ФЧ-6 по коду выглядит ЗАКРЫТЫМ** — отказ проекции репортится базисом, отчёт не валится (`backend/internal/pipeline/status.go`, греп `RebillBasisFailed`); **ФЧ-7 отдан проверкой** в вайр-батч (воспроизвести панику поверх пойманного потолка, чинить только если воспроизводится); **ФЧ-2/ФЧ-3/ФЧ-8 НЕ ПРОВЕРЕНЫ никем** и остаются живым остатком строки. | дофикс-промт ЛИБО попутно ближайшим паком | **D39.149**, **D39.150** | | 198 | **Апгрейд движка стирает замечания и счётчики книги БЕЗВОЗВРАТНО — композиция двух половин, каждая известна по отдельности** (приёмка P7, линза «вне карты», обе половины пере-прочитаны оркестратором). Платформа при смене `manifest_key` сносит ВСЕ `unit_resolutions` книги (`platform/internal/pgstore/readmodel.go:164-165`), рассчитывая, что поток их пере-наполнит; движок анонсирует юнит РОВНО ОДИН РАЗ за жизнь книги — ключ `unit::::` БЕЗ метки нарезки (`backend/internal/pipeline/events.go:399-400`), а леджер анонсов переживает прогоны (`backend/internal/store/outbox.go:96` «already announced… by one that ran before it») ⇒ совпавшие координаты не переанонсируются НИКОГДА. Обостряется порядком: долг на материализацию ставится только на ГРАНИЦАХ работы, поэтому первая зачистка после апгрейда случается в КОНЦЕ первого пост-апгрейдного прогона и сносит замечания ТОГО ЖЕ прогона, за который заплачено. Следствия на проводе: «0 из N» на переведённой книге навсегда · шкала снова предлагает купить переведённое · замечания читателя исчезают. **Лечится с обеих сторон:** движковая половина — метка нарезки в ключе анонса (решение зоны движка), платформенная — не сносить вслепую либо восстанавливать из экспорта. ⚠ Гейт холодного прогона: смысл упражнения — гонять книгу против МЕНЯЮЩЕГОСЯ движка, то есть первый же апгрейд обнулит библиотеку | бэкенд + платформа | **скоро (до первого реального пользователя И до холодного прогона с апгрейдами)** | связка: решение по ключу анонса в движке → правка платформы | приёмка P7 (D39.153) | | 201 | **Движковое «Глава N» доезжает читателю ВНУТРИ текста, обходя дисциплину `heading: null`** (линза шва P7, пере-прочитано оркестратором): `backend/internal/pipeline/export.go:58`=`ApplyHeading` (испр. оркестратором №20 30.08: якорь уезжал с `:230` и с `:266` — код растёт) приклеивает детерминированный порядковый к экспортному тексту первой юнит-главы (`ce.FinalText = chunk.ApplyHeading(...)`), колонка `Source` при этом остаётся heading-stripped. Платформа переносит обе как есть и честно отдаёт `heading: null` — то есть клиент нарисует СВОЙ порядковый на языке своего интерфейса над абзацем, который уже начинается с русского «Глава N», а исходная колонка соответствующего маркера не несёт: пара визуально рассинхронизирована на каждой первой главе. Конкретное следствие открытого К-2 контракта; родня движковой строки **160** (глава без заголовка) | бэкенд | когда-нибудь (с 160) | отдельное решение | приёмка P7 (D39.153) | | 202 | **Живой перевод книги НАСКВОЗЬ через API платформы не гонялся НИ РАЗУ** (obstacle сессии P7, подтверждён приёмкой): всё после «прогон стартовал и остановился» — подпись банка, halt на потолке, резюм после пополнения — покрыто батареей против живого Postgres, но с движком-заглушкой; настоящий манифест, сайдкар банка и причины флагов будут ПЕРВЫМИ данными, форму которых платформа не сочинила сама. Форма проверки (решена): только через API, как ходил бы клиент — интейк → старт → живой движок с ключами провайдера → поток событий → подпись и продолжение → чтение глав/юнитов/замечаний/банка и сверка с тем, что движок реально произвёл; качество перевода НЕ предмет (полигон). ⚠ **Цена ≈$0.05 СНЯТА как протухшая** (D39.179 п.1: пере-пин DeepSeek, множитель ×4.47; испр. 02.09). Замер 31.08 на ровно такой десятиглавой книге: **куплено $0.436110** при собственной проекции движка **`projected_book_usd = 1.1377277707`** и полном оттоке кассы **≈$1.44** (§4 отчёта). ⚠ Это цена НЕПОЛНОГО захода — доставлено 3 юнита из 14; как смету для покупателя брать нельзя. ⚠ Путь ключей платформы — переменная `TM_PLATFORM_ENGINE_KEYS_PATH`, требует АБСОЛЮТНОГО пути (греп по `platform/internal/config/`). **Решение владельца 20.08: ПОСЛЕ холодного прогона движка** — гонять одну неготовую систему против другой смысла нет | платформа | скоро (⚠ прежний гейт «холодный прогон движка» ПАЛ 31.08; живой блокер теперь один — файл ключей платформы `TM_PLATFORM_ENGINE_KEYS_PATH`, лечение операционное и $0) | короткая сессия по промту оркестратора | слово владельца 20.08, D39.153 | @@ -185,7 +185,7 @@ | 243 | **Остаток аудита доков 30–31.08: 19 удержанных находок НЕ применены** (аудит — 5 линз + верификатор на каждую, 57 находок, 55 удержаны, 36 применены сменой №20). Перечень: ~~**arch-3**~~ **ЗАКРЫТ 31.08 — разбор телом D39.179 п.5** (был вдвое больше заявленного: 51 указатель вместо 13, и дороже адресов оказались ЛОЖНЫЕ КЛЕЙМЫ) · **arch-5** (правило языка знает две корзины, `reader.txt` — третья) · **arch-7** (§2 закона шва: дисциплина флока не описывает новый глагол-писатель) · **arch-9** (реестр загейченных триггеров не знает нажатых 30.08) · ~~**arch-10**~~ и ~~**arch-11**~~ **ЗАКРЫТЫ 02.09** (числа словаря событий сняты в пользу кода; отвергнутый ключ назван отвергнутым) · **arch-12** (шапка `09-target` сама зовёт себя неполной — строку под таблицей слоёв надо внести; ⚠ ЖИВ на 02.09: греп `D39.181` по `docs/architecture/09-target-architecture.md` — 0 хитов, греп `D39.182` — 0 хитов, то есть лендинги 31.08 в док слоёв не внесены) · **contract-8** (эррата 15.08-в в шапке D-лога указывает на промт, уехавший в архив) · **contract-10** (`Export.failure_code` «becomes an enum with the first built format» — формат построен, условие наступило) · **progress-6/7/8/10/11/12/13/14/15** (мелочь CURRENT-STATE и строк бэклога: протухшие «запушена»/«строка 200»/якорь `miner_emit.go`/дубль 238 внутри 160 и пр.). ⚠ Отчёт аудита жил в песочнице сессии №20 и умирает с ней — здесь ЕДИНСТВЕННЫЙ носитель списка; воспроизведение = повторный аудит (5 агентов, ~2 часа) | оркестратор | скоро | пройти списком | аудит доков 30–31.08, сдача смены №20 | | 244 | **Гейт якорей на пре-коммите ломается всякий раз, когда зона правит КОД и СВОЙ реестр одним незакоммиченным деревом** — и врёт в обе стороны. Механика: хук судит ЗАКОММИЧЕННЫЙ док против РАБОЧЕГО кода, поэтому пере-нацеленные, но не залёнджённые якоря читаются как битые. Замерено на приёмке P12 31.08: у оркестратора хук напечатал 13 битых якорей `platform/docs/DEFECT_REGISTER.md`, у зоны `counts.py --lint` на том же дереве дал **0**; права зона — в HEAD `internal/runs/runs.go:323`, в рабочем `:347`, и токен по новому адресу на месте. ⚠ Обратная сторона опаснее и не замерена: якорь, ставший битым ПО-НАСТОЯЩЕМУ, тем же механизмом может оказаться зелёным. Свойство общее, не про этот пак | оркестратор | когда-нибудь | либо судить обе стороны из одного состояния (`--from-index` уже есть — проверить, покрывает ли он случай), либо печатать, что сравниваются РАЗНЫЕ состояния | приёмка P12 оркестратором №21, 31.08, разрешено командой | | 245 | **Pathspec-форма коммита молча роняет UNTRACKED-файлы, и сломанный коммит выглядит нормальным до первого чужого прогона.** `git commit -- <пути>` обходит ИНДЕКС и берёт рабочее дерево только для ОТСЛЕЖИВАЕМЫХ путей: предварительный `git add` нового файла она игнорирует. Поймано на лендинге P12 31.08 — коммит `e1cb692` унёс `migrations.sha256`, уже ссылавшийся на три миграции, а сами миграции 00029/00030/00031 и три теста остались снаружи; починено амендом секундного неопубликованного коммита при пустом индексе (`0a680a3`). ⚠ Канон git-координации в `CLAUDE.md` объясняет про pathspec ТОЛЬКО то, что она не трогает чужой индекс — то есть учит половине правды и ровно этим создаёт ловушку. Норма, которую предлагаю вписать: новые файлы стейджить явно и проверять состав `git show --name-only`, а не доверять форме. ⚠ **ПОЛОВИНА ПОСТРОЕНА 31.08** (`94381bb`, испр. 02.09): в `docs/scripts/githooks/pre-commit` стоит warn-блок, который перед каждым коммитом печатает неотслеживаемые файлы в каталогах коммита. Живой остаток — блок ПРЕДУПРЕЖДАЕТ, но не блокирует, и на свежем клоне хук вообще не установлен (строка 220) | оркестратор | скоро (решение владельца — его канон) | одна строка в `CLAUDE.md` §«Git-координация мультисессий»; вписывает владелец или оркестратор по его слову | лендинг P12 оркестратором №21, 31.08 | -| 246 | ⚠ **ДВЕ КОПИИ ПОЛОСЫ ОТКАЗОВ 10–19 ОБЕЩАЮТ РАЗНОЕ — потребитель держит гарантию, которую производитель ОТОЗВАЛ.** Движок (`backend/cmd/tmctl/main.go:53`=`Nothing was written` is NOT the band's promise any more): «„Nothing was written“ is NOT the band's promise any more … **exit 15 legitimately answers with files on disk**». Платформа (`platform/internal/ingest/exit.go:38`=`nothing this process would have written was written`): «… and nothing this process would have written was written». ⚠ Опасность не теоретическая: по `PD-196` интейк действует по полосе РАЗРУШИТЕЛЬНО (отклоняет книгу и удаляет загрузку), а `exit 15` теперь легитимно оставляет файлы на диске. Хвост: движковый `exitBookIncomplete = 16` у платформы константы НЕ имеет вовсе (её словарь 10·11·12·13·14·15·19). ⚠ **Денежная половина ЦЕЛА в обеих копиях** (`nothing was spent` — по одному хиту в каждой), поэтому запрет отказывать классом полосы там, где деньги уже потрачены, в силе. Предсказано п.6 закона шва 17 | платформа (правка) + оркестратор (маршрут) | СРОЧНО | зона платформы приводит свою копию к движковой ЛИБО обе стороны идут в ратификацию, если расхождение намеренное | пак «деньги и честность», находка A15 вне заказа, 31.08; пере-проверено оркестратором дословно обеими копиями | +| 246 | ⚠ **ДВЕ КОПИИ ПОЛОСЫ ОТКАЗОВ 10–19 ОБЕЩАЮТ РАЗНОЕ — потребитель держит гарантию, которую производитель ОТОЗВАЛ.** Движок (`backend/cmd/tmctl/main.go:53`=`Nothing was written` is NOT the band's promise any more): «„Nothing was written“ is NOT the band's promise any more … **exit 15 legitimately answers with files on disk**». Платформа (`platform/internal/ingest/exit.go:38`=`nothing this process would have written was written`): «… and nothing this process would have written was written». ⚠ Опасность не теоретическая: по `PD-196` интейк действует по полосе РАЗРУШИТЕЛЬНО (отклоняет книгу и удаляет загрузку), а `exit 15` теперь легитимно оставляет файлы на диске. Хвост: движковый `exitBookIncomplete = 16` у платформы константы НЕ имеет вовсе (её словарь 10·11·12·13·14·15·19). ⚠ **Денежная половина ЦЕЛА в обеих копиях** (`nothing was spent` — по одному хиту в каждой), поэтому запрет отказывать классом полосы там, где деньги уже потрачены, в силе. Предсказано п.6 закона шва 17 | платформа (правка) + оркестратор (маршрут) | СРОЧНО ⚠ **ВЕС ПЕРЕ-СНЯТ 04.09 (сверка контролёра, пере-проверено): «разрушительно по полосе» ПЕРЕОЦЕНЕНО.** Интейк удаляет загрузку ТОЛЬКО на классе 11 (`platform/internal/books/parse.go`, греп `only source_unreadable removes it`), а exit 15 производит один глагол — `bank-apply`. Живой остаток — комментарий `platform/internal/ingest/exit.go` плюс константа `ExitBookIncomplete = 16`, которую дверь выдачи и так добавит; идёт РАЙДЕРОМ платформенного пака, а не срочным пунктом. | зона платформы приводит свою копию к движковой ЛИБО обе стороны идут в ратификацию, если расхождение намеренное | пак «деньги и честность», находка A15 вне заказа, 31.08; пере-проверено оркестратором дословно обеими копиями | | 247 | **§2.2 закона раскрытия опровергает себя следующей же строкой — эррата зонного дока.** Формальная фраза требует «держит ОБА операнда сравнения и обязано их НАПЕЧАТАТЬ», а её собственный пример тут же говорит обратное: честная форма — НАЗВАТЬ ОСЬ («снапшот разошёлся» честно, «конфиг/промпты изменились» ложно). ⚠ **Ратифицированный текст D39.181 п.1 требования «напечатать» НЕ СОДЕРЖИТ ВОВСЕ** — оно живёт только в `backend/docs/DISCLOSURE_LAW_DESIGN.md`, значит противоречия с ратификацией нет и решает ЗОНА, не владелец. ⚠ Довод «граница прячет имена моделей и хеши» ОПРОВЕРГНУТ исполнением: эти значения уже едут по тому же stderr штатным INFO-логом, включая `memory_version=<12 hex>` — значение того самого поля. Цена бездействия на живых данных = НОЛЬ (единственная сдвинувшаяся ось — хешевая, печать дала бы две несравнимые строки SHA) | бэкенд | когда-нибудь | эррата к §2.2: операнды называются осью, а не значением | приёмка D39.182 + разведка оркестратора 31.08 | | 248 | **Полнота самообъявления о правках чужих тестов ничем не проверяется — и трижды оказалась неполной.** P11 назвала файл, которого не трогала; P12 не назвала тест, у которого переписаны ОБА утверждения; сессия пака «деньги и честность» в первой редакции комментария утверждала неверное о силе собственной правки. ⚠ **Мой метод проверки был слабее, чем я его подал:** греп `^[-+].*t\.(Error|Fatal)` ловит строку СООБЩЕНИЯ, а утверждение — это строка СРАВНЕНИЯ, и она другая (замер: греп локализует утверждение в 1 случае из 475). Предложение разведки: warn-only гейт-детектор при лендинге — список пред-существующих тестов с изменёнными строками утвержденческой формы ВНУТРИ пред-существующих тел; прототип ~25 строк sh прогнан на двух лендингах и указал ровно на `bankfixpack_test.go`. Площадка есть — `docs/scripts/githooks/pre-commit` уже warn-only. ⚠ Ложняки измерены: целиком новый `t.Run` внутри старого `func` даёт срабатывание (1 из 6 на P12) | оркестратор | скоро | гейт-детектор warn-only + пункт чек-листа приёмки | разведка оркестратора 31.08 по вопросу владельца | | 249 | **Девять рядов бэклога потеряли слово веса, и гейт на них НЕ краснеет.** ⚠ **Лечение ПОСТРОЕНО (сверено кодом 02.09): вес судится ПРЕФИКСОМ ячейки** — `docs/scripts/counts.py`, греп `BACKLOG_WEIGHTS` (три слова: «блокер-очереди» · «скоро» · «когда-нибудь»), и «скоро» считается тем же префиксом. Этим убита ВТОРАЯ половина класса: подстрока ловила слово в ПРОЗЕ, и фраза «переведена из «скоро»» ре-добавляла ряд в счёт — число скакнуло **53 → 56** при одной новой строке (замер 02.09, пере-счёт скриптом). ⚠ Гейт рождён ЗЕЛЁНЫМ, а не красным: девять известных рядов внесены «дедовщиной» — греп `WEIGHT_GRANDFATHERED` там же, ряды **5 · 13б · 94 · 96 · 97 · 149 · 205 · 221 · 246**. **ЖИВОЙ ОСТАТОК — сами ячейки:** у 96/97 прочерк ЗАКОНЕН (надгробия строк, уехавших в зонный бэклог, D39.84), остальные семь потеряли вес молча и чинятся оркестратором — каждая починенная выходит из списка дедовщины. ⚠ Два ряда шире класса: **149** («исполнен и заленден 10.08») и **205** («сделано 21.08») объявляют себя ИСПОЛНЕННЫМИ прямо в колонке веса, хотя по правилу таблицы закрытые строки в ней не живут — это либо живой остаток без веса, либо непойманный класс C; **246** несёт самодельное «СРОЧНО», которого в словаре нет. | оркестратор | скоро ($0, гигиена трекера) | правка семи ячеек → выход из `WEIGHT_GRANDFATHERED` | ревизия доков 02.09, приёмка контролёра | @@ -385,7 +385,7 @@ 3. **`rebill_model_moved_rows`** — второе новое поле `status --json` сверх названного промтом одного; говорит, какая часть суммы завышена из-за смены модели стадии. Аддитивно, платформой игнорируется (её аллоулист не берёт ни одного `rebill_*`); без него человекочитаемая строка и текст отказа перестают говорить дословно одно и то же. **РЕШЕНИЕ ВЛАДЕЛЬЦА: оставить.** 4. **Ошибок в промте не нашла.** -### 03.09 — ДОФИКС по приёмке №22 (наряд `docs/BACKEND_DOFIX_2026-09-03.md`, сессия `textmachine-77`) +### 03.09 — ДОФИКС по приёмке №22 (наряд `docs/archive/prompts/BACKEND_DOFIX_2026-09-03.md`, сессия `textmachine-77`) > **Состояние git на входе в дофикс — важнее прочего, потому что наряд писан по другому.** Наряд говорит «в индексе лежит незакоммиченная работа двух смен». К моменту исполнения владелец уже закоммитил её в ЛОКАЛЬНЫЙ `e85295d` «temp», а `origin/main` был обновлён ПРИНУДИТЕЛЬНО на `ea54355`, в историю которого `temp` не входит (`git merge-base --is-ancestor e85295d origin/main` → нет). По слову владельца я откатил temp и подтянул наряды двумя командами: `git reset --mixed 2a63c37`, затем `git merge --ff-only origin/main` (перемотка — `ea54355` растёт из того же `2a63c37`). Перед этим поставил метку **`temp-backup-e85295d`**, чтобы коммит с работой обеих смен нельзя было потерять; снимать её до лендинга не надо. Целостность проверена, а не предположена: изменённые файлы совпали с temp **бит-в-бит** (сравнение хешей двух диффов), пять добавленных файлов снова стали неотслеживаемыми и лежат на диске побайтно как в коммите (`git hash-object` против `git rev-parse e85295d:<файл>`). В дереве НА МОМЕНТ ОТКАТА было 44 файла: 22 мои, 21 платформы, один общий журнал; дальше число растёт у обеих смен по мере работы. **Индекс пуст, не коммичу.** > diff --git a/docs/BACKEND_DOFIX_2026-09-03.md b/docs/archive/prompts/BACKEND_DOFIX_2026-09-03.md similarity index 95% rename from docs/BACKEND_DOFIX_2026-09-03.md rename to docs/archive/prompts/BACKEND_DOFIX_2026-09-03.md index 5e168f82..a0b726a2 100644 --- a/docs/BACKEND_DOFIX_2026-09-03.md +++ b/docs/archive/prompts/BACKEND_DOFIX_2026-09-03.md @@ -1,5 +1,12 @@ # ДОФИКС бэкенд-паку «число согласия на пути второй покупки» — по приёмке оркестратора №22 (03.09.2026) +> ⚠⚠ **АРХИВ. НАРЯД ОТРАБОТАН — ИНСТРУКЦИИ ОТСЮДА НЕ ИСПОЛНЯЮТСЯ.** +> Выдан 03.09 по приёмке пака «число согласия», отработан той же сессией, принят приёмкой второго +> круга (`D39.187`). Исход: девять пунктов из десяти исполнены и подтверждены исполнением; остаток — +> развилка операторской строки прибита с одной стороны, граница `bound()` без пина, три числа отчёта. +> Остаток НЕ потерян: он пунктом 6 выданного пака `BACKEND_WIREBATCH_SESSION_PROMPT.md`. +> ⚠ Часть якорей мертва по построению — пак снял тексты, на которые они указывали. + > **Роль:** бэкенд, та же сессия, что отработала пак. **Зона записи:** `backend/` + своя секция > «Бэкенд» в `docs/PROGRESS.md`. Чужие зоны читаешь, не правишь. **Не коммитишь** и не трогаешь индекс > и историю — запреты и причина: `CLAUDE.md`, «Git-координация мультисессий». diff --git a/docs/PLATFORM_P13_DOFIX_2026-09-03.md b/docs/archive/prompts/PLATFORM_P13_DOFIX_2026-09-03.md similarity index 96% rename from docs/PLATFORM_P13_DOFIX_2026-09-03.md rename to docs/archive/prompts/PLATFORM_P13_DOFIX_2026-09-03.md index 7427b690..2a12cde5 100644 --- a/docs/PLATFORM_P13_DOFIX_2026-09-03.md +++ b/docs/archive/prompts/PLATFORM_P13_DOFIX_2026-09-03.md @@ -1,5 +1,12 @@ # ДОФИКС платформенному паку P13 «шов возврата оплаченного прогона» — по приёмке оркестратора №22 (03.09.2026) +> ⚠⚠ **АРХИВ. НАРЯД ОТРАБОТАН — ИНСТРУКЦИИ ОТСЮДА НЕ ИСПОЛНЯЮТСЯ.** +> Выдан 03.09 по приёмке пака P13, отработан той же сессией, принят (`D39.188`). Исход: П1–П3 и П6 +> исполнены и красны на двадцати посадках приёмки; П4 зона ОТКАЗАЛАСЬ исполнять — и отказ был ПРАВ, +> предпосылка наряда на её дереве была ложной (ряд стоял `open`, гейт и база согласованно печатали 12). +> Остаток — П5, записка о предусловии хоста; он пунктом 4 выданного пака +> `PLATFORM_EXPORT_SESSION_PROMPT.md`. + > **Роль:** платформа, та же сессия, что отработала пак P13. **Зона записи:** `platform/`. Чужие зоны > читаешь, не правишь. **Не коммитишь** и не трогаешь индекс и историю — запреты и причина: > `CLAUDE.md`, «Git-координация мультисессий». Норматив — `platform/docs/ENGINEERING_STANDARDS.md`. diff --git a/docs/NEXT_PACKS_PLAN.md b/docs/archive/reports/NEXT_PACKS_PLAN_2026-09-03.md similarity index 96% rename from docs/NEXT_PACKS_PLAN.md rename to docs/archive/reports/NEXT_PACKS_PLAN_2026-09-03.md index 4ce62da1..e1baf92d 100644 --- a/docs/NEXT_PACKS_PLAN.md +++ b/docs/archive/reports/NEXT_PACKS_PLAN_2026-09-03.md @@ -1,5 +1,15 @@ # ПЛАН ДВУХ СЛЕДУЮЩИХ ПАКОВ — бэкенд и платформа (оркестратор №22, 03.09.2026) +> ⚠⚠ **АРХИВ. ПЛАН ОТРАБОТАН — РЕШЕНИЯ ПРИНЯТЫ, ПРОМТЫ ВЫДАНЫ. ИНСТРУКЦИИ ОТСЮДА НЕ ИСПОЛНЯЮТСЯ.** +> Составлен 03.09, сведён с разбором контролёра (Fable 5.1) по всему бэклогу и всему журналу, +> ратифицирован `D39.190` 04.09. Живые носители его содержания: решения — **D39.190** (160 отложена +> ПОРЯДКОМ, 142 после полигона, пере-снапшот батча единым актом) · состав паков — выданные промты +> `BACKEND_WIREBATCH_SESSION_PROMPT.md` и `PLATFORM_EXPORT_SESSION_PROMPT.md` · санкция платных +> прогонов — **D39.189** с эрратой 04.09-а о механизме потолка. +> ⚠ **Улики плана, которых не было больше нигде, ПЕРЕНЕСЕНЫ в носители 04.09 перед архивацией:** +> пере-вес 246 и «ФЧ-6 по коду закрыт» — в ячейки бэклога **246** и **197** · судьба 131/105(а)/14 и +> состав окна — в ячейку **182** · остаток `PD-438` — в его ряд регистра. Ничего не потеряно с файлом. + > **Статус: РЕДАКЦИЯ 2 — сведена с разбором контролёра (Fable 5.1) 04.09; десять его обязательных > правок приняты, каждая с уликой, и две его находки понизили вес моих собственных утверждений.** Промты по нему НЕ выдаются, пока оркестратор и контролёр (Fable 5.1) > не скажут «ок» друг другу — распоряжение владельца 03.09. Файл — предмет этой сверки. diff --git a/platform/docs/DEFECT_REGISTER.md b/platform/docs/DEFECT_REGISTER.md index c12096f4..905b6fc3 100644 --- a/platform/docs/DEFECT_REGISTER.md +++ b/platform/docs/DEFECT_REGISTER.md @@ -58,7 +58,7 @@ | PD-420 | bug | minor | `internal/pgstore/runs_test.go` `TestAClaimThatLostARaceToAReleaseIsRetriedAndNotAnError` | **Тест гонки холда против релиза краснеет под ПАРАЛЛЕЛЬНЫМИ батареями, а зона ратифицировала рецепт, который их требует.** `D39.159` §2 предписывает сажать мутации в КОПИЮ дерева, и всякая сессия, которая делает это всерьёз, гоняет несколько батарей разом. Замер пака P11: при трёх параллельных прогонах краснеет в ЧИСТЫХ копиях (2 раза из 15); в СЕРИЙНОМ прогоне зелен — пере-проверено трижды подряд отдельным прогоном, все три `ok`. ⚠ **ВТОРАЯ ТОЧКА, 29.08, внешнее ревью:** упал 1 раз из 4 ПОЛНЫХ прогонов зоны со всеми гейтами — то есть краснеет и без параллельных копий, просто редко. Изолированно 5/5, пакет целиком 2/2, три последующих полных прогона чистые; сообщение поймать не удалось, и ревьюер честно остановился на «редком флейке контенции», диагноз НЕ установлен. Пакет ни одним коммитом эры P11 не тронут. ⚠ Обе точки вместе сдвигают формулировку: это не «краснеет от параллельной нагрузки», а «редкая гонка, которую нагрузка делает вероятнее», — и мой первый диагноз («флейк параллельных батарей») был выведен из совпадения, ровно как в `PD-423`. Меряет ресурс, общий для копий на машине. ⚠ Цена не косметическая: **красная ЧИСТАЯ копия маскирует дельту**, а красный прогон посадки читается как «мутация поймана», когда она не поймана, — ровно та ложная улика, ради которой мутации и сажают. Обход пака — судить по ДЕЛЬТЕ множеств, а не по коду выхода; лечение — изоляция ресурса либо честный скип под нагрузкой ⚠ **пак P12 (30–31.08): пере-замерена ПОСЛЕ фикса `PD-369`, серийно — 80 из 80 зелёных, 0 FAIL, 0 SKIP** (`-count=80`, счёт по `^--- PASS`). Это снимает ПЕРВУЮ из двух точек строки по построению: флейк был не в тесте, а в том, что исчерпание раундов отвечало 500, и тест это честно ловил. ⚠ **ВТОРАЯ точка (редкая гонка контенции, 1 из 4 полных прогонов, диагноз НЕ установлен) пере-замерена под ТРЕМЯ параллельными полными батареями в чистых копиях: 18/18 пакетов в каждой, 0 красных, EXIT=0 ×3.** Это ОДНА точка, а не опровержение: строка сама говорит, что краснеет редко (1 из 4), и три чистых прогона такой частоты не исключают. Строка остаётся открытой на ней с дополненным замером; закрыть её может только серия, а не прогон. | open | пак P11, мутационная кампания (15 прогонов) + пере-проверка серийными прогонами | | PD-423 | standards | minor | `internal/runner/systemd_test.go` `TestARunIsBoundedByItsOwnCgroup`, `docs/STACK_DECISIONS.md` «Гейты батареи» | **Батарея зоны требует ЧЕТВЁРТОГО условия хоста, которого рецепт не называет: пользовательский менеджер systemd должен РЕАЛЬНО применять `MemoryMax` к транзиентным юнитам.** Замерено на этом хосте 29.08: тест трижды подряд зелен в полных батареях (`baseline2`, `final2`, `final4`), затем **пять раз подряд красен в изоляции** — при неизменном коде пакета, которого пак не касался вовсе. Причина установлена ВНЕ батареи и вне Go: `systemd-run --user --scope -p MemoryMax=64M …` даёт процессу спокойно занять 400 МиБ и выйти с кодом 0. ⚠ **МЕХАНИЗМ уточнён приёмкой оркестратора №19, и уточнение решает, воспроизводимо ли это:** «systemd не применяет потолок» верно по симптому и мимо по причине. Свойство ДОЕХАЛО — `systemctl --user show -p MemoryMax` печатает `67108864`; делегирование в порядке — `memory pids` и в `cgroup.controllers`, и в `subtree_control`. Пропал не потолок, а cgroup-КАТАЛОГ: в `app.slice` нет ни одного scope-каталога, а `cut -d: -f3 /proc/self/cgroup` для оболочки даёт **`/init.scope`**. То есть вызывающий процесс живёт ВНЕ `user@.service`; `systemd-run --user` заводит юнит в модели менеджера, а процесс остаётся в исходном cgroup, и лимита не получает никто — молча. ⚠ Отсюда и наблюдение «условие отваливается между двумя прогонами одной сессии»: оно зависит от того, из какого cgroup стартовал прогон. Тест при этом ПРАВ и его сообщение точное («check that the leaf cgroup of tm-runs.slice has memory.max»): он ловит ровно то, ради чего написан, — что потолок памяти прогона на этом хосте иллюзорен. ⚠ Следствие для процесса, а не только для теста: рецепт `STACK_DECISIONS` называет три условия батареи, а их четыре, и четвёртое — свойство ХОСТА, которое может отвалиться между двумя прогонами в одной сессии, что здесь и произошло. Сессия, наступившая на это, потратит время на поиск дефекта в своём диффе. ⚠ Предложенная этой строкой формулировка четвёртого условия («вызывающий процесс обязан жить ВНУТРИ `user@.service`», проверка `cut -d: -f3 /proc/self/cgroup` ≠ `/init.scope`) ОПРОВЕРГНУТА точками 2 и 3 ниже и СНЯТА из рецепта (`PD-432`). Живой остаток лечения — дать тесту различать «хост не применяет лимит» (честный скип с причиной) и «раннер не передал лимит» (настоящий отказ) ⚠⚠ **ВТОРАЯ ТОЧКА, 29.08, и она ПРОТИВОРЕЧИТ механизму выше — строку не закрывать, а пере-проверить.** Пак `sqlc` на ТОМ ЖЕ хосте и при том же `cut -d: -f3 /proc/self/cgroup` = **`/init.scope`** получил тест **зелёным 5 из 5 в ИЗОЛЯЦИИ** (протокол, в котором приёмка №19 видела 5 из 5 красных) плюс трижды в полных батареях; скипов в этих прогонах **ноль** — проверено по логам, то есть `systemdOrSkip` и проверка `python3` не срабатывали и тест НЕ был пустым: он требует настоящего `oom-kill` после касания 400 МиБ под `MemoryMax=64M`. Прямая проба механизма: `systemd-run --user --scope -p MemoryMax=64M -- sh -c 'cut -d: -f3 /proc/self/cgroup'` печатает **`/user.slice/user-1000.slice/user@1000.service/app.slice/run-….scope`**, то есть процесс ВСЁ-ТАКИ попадает внутрь `user@.service`, а не остаётся в исходном cgroup. Сам `tm-runs.slice` при этом существует и лежит глубже, чем ищут: `user@1000.service/**tm.slice**/tm-runs.slice` (`cgroup.controllers` = `memory pids`). **Следствие практическое:** предложенная этой же строкой одна команда-проверка (`/proc/self/cgroup` не должен давать `/init.scope`) на этом хосте даёт ЛОЖНЫЙ ОТРИЦАТЕЛЬНЫЙ — она говорит «условие не выполнено» там, где лимит применяется и тест честно зелёный. Значит cgroup ВЫЗЫВАЮЩЕГО процесса условие не предсказывает, диагноз строки неполон, и в рецепт `STACK_DECISIONS` эту команду в нынешнем виде вносить нельзя. Что различает две точки — не установлено; кандидат — состояние `cgroup.subtree_control` целевого среза в момент прогона (сейчас у `tm-runs.slice` он пуст, а systemd включает контроллер сам при старте юнита с лимитом). ⚠ **ТРЕТЬЯ ТОЧКА, пак P12 (30–31.08), и она согласна со второй:** у оболочки этой сессии `cut -d: -f3 /proc/self/cgroup` даёт **`/`** (не `/init.scope` и не путь внутри `user@.service`), а `TestARunIsBoundedByItsOwnCgroup` при этом ЗЕЛЁН в полной батарее со скипами 0 — проверено четырьмя полными прогонами. Прямая проба `systemd-run --user --scope` кладёт процесс в `…/user@1000.service/app.slice/run-….scope`; `tm-runs.slice` существует, `cgroup.controllers` = `memory pids`, а его `cgroup.subtree_control` ПУСТ — и тест всё равно зелен. То есть команда-проверка не предсказывает условие ни в одну сторону, и она **СНЯТА из рецепта** `STACK_DECISIONS` этим паком (см. `PD-432`). Что различает точки — по-прежнему НЕ УСТАНОВЛЕНО; строка остаётся открытой на диагнозе, а не на рецепте. | open | пак P11 (финальная батарея; воспроизведено голым `systemd-run` вне Go) | | PD-250 | vuln | minor | `cmd/tmplatformd/main.go` (слушатель метрик) | **`/metrics` отдаётся БЕЗ аутентификации; вся защита — привязка к `127.0.0.1`.** Для одной VM это честная граница, и она записана (STACK §24). Но на хосте с несколькими пользователями любой локальный процесс читает оперативную картину сервиса, а на деплое, где слушатель однажды переедет на `0.0.0.0` «чтобы Prometheus дотянулся», защиты не останется вовсе. Денег в метриках нет (D39.84), поэтому это minor, а не major. Лечение — bearer-токен на слушателе или mTLS, решать при первом внешнем Prometheus ⚠ **ПАК P8-REVIEW 24.08: это ТОТ ЖЕ факт, что `PD-179`, и он стоит в регистре в ДВУХ статусах одновременно** (`accepted-risk(платформа P5, 11.08)` против `open`). Код и ручка одни: `cmd/tmplatformd/main.go` `serveMetrics` без аутентификации, дефолт `127.0.0.1:9464`; рантбук `deploy/README.md` называет строкой риска именно `PD-179`. Своя добавка у этой строки есть (многопользовательский хост), но статус один факт должен нести один. Предложение пака: свести ⚠⚠ **Условие сведения, найденное рефутером:** у `PD-179` довод про ОДНУ VM, а добавка этой строки — многопользовательский хост, где любой локальный непривилегированный процесс скрейпит экспозицию, — в `PD-179` ОТСУТСТВУЕТ. Плюс при сведении из выборок безопасности исчезает класс `vuln` (у `PD-179` он `hardening`). Сводить только ВМЕСТЕ с перенесённой фразой и с пометкой класса | open | research/28 §9 (пинг оркестратора №17), сверено P7 | -| PD-438 | bug | **major** | `internal/ingest/tail.go` `apply` (греп `ErrForeignStreamAhead`), `internal/ingest/tail.go` `tailFrom` (греп `mine := want`), `internal/runs/reconcile.go` `drainJournal` | **Владение потоком не переживало проход свипа, и чужие события ложились на оплаченную попытку.** `mine` — возвращаемое значение, а не колонка: следующий проход выводит его заново из `pos.LastSeq > 0`. Пока тейлер ПРОХОДИЛ мимо чужого handshake'а, двигая байтовый хинт, следующий проход читал чужую область с курсором, который говорит «это наше»: чужой `ceiling` ставил `paused` живому оплаченному прогону, `unit_done` писал главы, которых никто не покупал, а чужой `seq`, попавший на наш, давал `ErrPayloadConflict` и карантинил здоровую проекцию. ⚠ **Воспроизведено в двух вариантах, до и после правки P13** (копия дерева, `Tail` дважды — форма, в которой его зовёт `drainJournal`): на `HEAD 494c4ef` законный чужой hello травит проекцию (`pass 2 applied a FOREIGN event (seq [2])`), а чужой мажор карантинит; после пере-упорядочивания пункта 3 P13 ОБА травят — то есть заказанная правка расширила старый класс с законных чужих строк на любые. Конфликт payload воспроизводится одинаково на обеих версиях. ⚠ Лечение в дереве пака P13 (03.09): чтение ОСТАНАВЛИВАЕТСЯ на чужом handshake'е, если платформа именовала поток попытки и наши строки уже применены (`pos.LastSeq > 0`), и курсор на нём остаётся — владение выводится заново каждый проход, ценой одного пере-чтения строки. Прежняя семантика «пройти мимо» сохранена там, где она безопасна: пока `LastSeq == 0`, наш handshake ещё может лежать ниже по файлу (пин `TestAForeignStreamBeforeOursIsWalkedPastRatherThanStoppedOn`), и у безымянной легаси-попытки (`want == ""`) — пин `TestAnotherAttemptsStreamInTheSameJournalIsSkipped` зелёный. Пины: `TestAForeignStreamDoesNotOwnOurAttemptOnTheNextPass` (три формы чужого hello × три следующих строки). ⚠ **ДОФИКС 03.09: обоснование «вред ограничен по времени» ОПРОВЕРГНУТО приёмкой исполнением, и оно было моё.** Довод «чужой handshake ⇒ нашего процесса в книге уже нет» неверен: платформа отдаёт КАЖДОМУ спавну одной и той же попытки один и тот же id потока (`internal/runs/spawn.go`, греп `engineStreamID(l.RunID, l.AttemptNo)`), а движок, найдя, что этот id уже писал события книги, минтит СВЕЖИЙ и продолжает (`backend/internal/pipeline/events.go`, греп `fresh := obs.NewTraceID()`). Значит «чужой» hello может писать ЖИВОЙ процесс нашей же попытки, и прогон способен простоять припаркованным весь свой срок. Радиус сужен опровергателем приёмки: путь — конъюнкция двух признанных сбоев (претензия на юнит, отчитавшаяся ошибкой, плюс исчезновение юнита без exit-marker), а не рядовой рестарт. **Наблюдаемость дана в том же дофиксе:** тейлер сообщает о парковке отдельным сигналом (`internal/ingest/tail.go`, греп `ErrForeignStreamAhead`) вместо тихого `nil`; свип пишет WARN с прогоном, попыткой и смещением; и парковка теперь СТОИТ РЯДОМ с карантином в условии канала починки (`maybeResync`, греп `!l.Quarantined && !parked`), то есть у припаркованной попытки снова есть свежесть через `tmctl status`. Пины: `TestTheParkIsReportedSoTheCallerCanTellItFromBeingCaughtUp` (без DSN), `TestAParkedAttemptStillGetsTheRepairChannel` (DSN). ⚠ Чего по-прежнему НЕТ: строки в `runs`, гейджа и колонки — парковка живёт длину одного прохода и в БД не пишется; дать ей строку значит завести колонку, то есть миграцию, а она этим нарядом не заказана | open | самопроверка пака P13 (веер, линза шва; воспроизведено сессией на копии) | +| PD-438 | bug | **major** | `internal/ingest/tail.go` `apply` (греп `ErrForeignStreamAhead`), `internal/ingest/tail.go` `tailFrom` (греп `mine := want`), `internal/runs/reconcile.go` `drainJournal` | **Владение потоком не переживало проход свипа, и чужие события ложились на оплаченную попытку.** `mine` — возвращаемое значение, а не колонка: следующий проход выводит его заново из `pos.LastSeq > 0`. Пока тейлер ПРОХОДИЛ мимо чужого handshake'а, двигая байтовый хинт, следующий проход читал чужую область с курсором, который говорит «это наше»: чужой `ceiling` ставил `paused` живому оплаченному прогону, `unit_done` писал главы, которых никто не покупал, а чужой `seq`, попавший на наш, давал `ErrPayloadConflict` и карантинил здоровую проекцию. ⚠ **Воспроизведено в двух вариантах, до и после правки P13** (копия дерева, `Tail` дважды — форма, в которой его зовёт `drainJournal`): на `HEAD 494c4ef` законный чужой hello травит проекцию (`pass 2 applied a FOREIGN event (seq [2])`), а чужой мажор карантинит; после пере-упорядочивания пункта 3 P13 ОБА травят — то есть заказанная правка расширила старый класс с законных чужих строк на любые. Конфликт payload воспроизводится одинаково на обеих версиях. ⚠ Лечение в дереве пака P13 (03.09): чтение ОСТАНАВЛИВАЕТСЯ на чужом handshake'е, если платформа именовала поток попытки и наши строки уже применены (`pos.LastSeq > 0`), и курсор на нём остаётся — владение выводится заново каждый проход, ценой одного пере-чтения строки. Прежняя семантика «пройти мимо» сохранена там, где она безопасна: пока `LastSeq == 0`, наш handshake ещё может лежать ниже по файлу (пин `TestAForeignStreamBeforeOursIsWalkedPastRatherThanStoppedOn`), и у безымянной легаси-попытки (`want == ""`) — пин `TestAnotherAttemptsStreamInTheSameJournalIsSkipped` зелёный. Пины: `TestAForeignStreamDoesNotOwnOurAttemptOnTheNextPass` (три формы чужого hello × три следующих строки). ⚠ **ДОФИКС 03.09: обоснование «вред ограничен по времени» ОПРОВЕРГНУТО приёмкой исполнением, и оно было моё.** Довод «чужой handshake ⇒ нашего процесса в книге уже нет» неверен: платформа отдаёт КАЖДОМУ спавну одной и той же попытки один и тот же id потока (`internal/runs/spawn.go`, греп `engineStreamID(l.RunID, l.AttemptNo)`), а движок, найдя, что этот id уже писал события книги, минтит СВЕЖИЙ и продолжает (`backend/internal/pipeline/events.go`, греп `fresh := obs.NewTraceID()`). Значит «чужой» hello может писать ЖИВОЙ процесс нашей же попытки, и прогон способен простоять припаркованным весь свой срок. Радиус сужен опровергателем приёмки: путь — конъюнкция двух признанных сбоев (претензия на юнит, отчитавшаяся ошибкой, плюс исчезновение юнита без exit-marker), а не рядовой рестарт. **Наблюдаемость дана в том же дофиксе:** тейлер сообщает о парковке отдельным сигналом (`internal/ingest/tail.go`, греп `ErrForeignStreamAhead`) вместо тихого `nil`; свип пишет WARN с прогоном, попыткой и смещением; и парковка теперь СТОИТ РЯДОМ с карантином в условии канала починки (`maybeResync`, греп `!l.Quarantined && !parked`), то есть у припаркованной попытки снова есть свежесть через `tmctl status`. Пины: `TestTheParkIsReportedSoTheCallerCanTellItFromBeingCaughtUp` (без DSN), `TestAParkedAttemptStillGetsTheRepairChannel` (DSN). ⚠ Чего по-прежнему НЕТ: строки в `runs`, гейджа и колонки — парковка живёт длину одного прохода и в БД не пишется; дать ей строку значит завести колонку, то есть миграцию, а она этим нарядом не заказана ⚠ **ОСТАТОК НАЗВАН 04.09 приёмкой:** лечение в дереве и заленджено (`6ae3e76`), но ПРИПАРКОВАННАЯ попытка не видна ни в `runs`, ни гейджем, ни колонкой — у этого класса нет ни одного из трёх сигналов, которые были у карантина, а `maybeResync` до дофикса такую попытку пропускал. Дофикс дал ей имя (`ErrForeignStreamAhead`), WARN с троттлингом и вход в ресинк; поверхностная видимость для ОПЕРАТОРА остаётся открытой и идёт райдером платформенного пака. | open | самопроверка пака P13 (веер, линза шва; воспроизведено сессией на копии) | ## Открытые — info | ID | Класс | Серьёзность | Где | Суть | Статус | Источник |