> ⚠ **ОТРАБОТАН И ПРИНЯТ 16.09 — акт `D39.255`, лендинг `af88680` (29 путей, $0).** > Инструкции ниже НЕ исполняются: пак закрыт. Закрыты строки **291** и **379**. Остаток — строки > **375** · **232** · **453**–**456**, и он принят вместе с паком. > ⛔ Пак пережил ПОТЕРЮ СЕССИИ: `textmachine-b1` построила его почти целиком и исчезла при переезде > окружения, не объявив работу завершённой; доводила `textmachine-main-b1` разделом ПЕРЕДАЧИ (ред. 5), > он и был сильнее тела. Сдача пришла по правилу остановки П4 — круги НЕ сошлись, и это объявлено честно. > ⭐ Строка **379** закрыта не чтением, а замером: на мутанте `answered &&` пин падает **8 из 8**, тогда > как ряд фиксировал 7 из 8 — вероятность стала гарантией (п.9 акта). > ⚠ Три опубликованных ключа качества сменили смысл (`ProcessedUnits`, `EchoDraftRecovered`, > эдит-числитель) — п.4 и п.5 акта; `D39.19` п.4 получил эрратой снятие гейта `DispFlagged`. # ⟶ ПЕРЕДАЧА ПАКА 15.09 (ред. 5) — ЧИТАЙ ЭТО ПЕРВЫМ > Оркестратор №23; прежняя сессия оркестратора `textmachine-11` оборвалась, адрес нынешней — в канале (П8). > Пак $0. **При расхождении этот раздел СИЛЬНЕЕ тела ниже** (§1–§13, редакция 4); прямые отмены тела перечислены > в П6. Тело остаётся описанием ПРЕДМЕТА: что заказано, почему и чем мерить. ## П1. Что случилось и что решит твой результат Пак выдан 11.09 сессии `textmachine-b1`. Она построила его почти целиком — 22 изменённых и 4 новых тестовых файла в `backend/` (+2850/−158), плюс отчёт в `docs/PROGRESS.md`; всего 27 путей, +3215/−158 — провела семь кругов адверсариального чтения и потерялась при переезде окружения, **не объявив работу завершённой**. ⇒ пак идёт, исполнителя у него нет, и слот бэкенда занят, пока пак не закрыт актом. **Твой результат — довести ЧУЖУЮ почти готовую работу до критерия §13 и сдать на приёмку.** Не перестраивать и не улучшать сверх заказа: предмет решён владельцем и построен. ⚠ **Почему это раздел того же промта, а не отдельный пак** (эррата 04.09-г в шапке `docs/architecture/05-decisions-log.md` велит круг над ГОТОВЫМ паком давать отдельным паком следующей сессии). Здесь пак НЕ готов — строки завершения нет, — и слот зоны один; копировать тело заказа в новый файл значило бы завести второй носитель того же предмета. Свежий глаз, ради которого эррата написана, у тебя есть по построению. По критерию §13 открыто СЕМЬ вещей — замерено мною 15.09, команды рядом: 1. **Круги не сошлись.** Седьмой круг (узкий, по починкам шестого) дал два мажора — С1 и С2, оба починены, но круга, проверившего эти починки, нет. Что круги находят дефекты в починках предыдущих, отчёт говорит о кругах 2–3 сам; у 4–7 это видно по их таблицам. 2. **Секции «Числа» нет,** хотя отчёт ссылается на неё трижды. Заголовков в секции b1 — 31, ни одного про числа: `awk '/^#### Пак «КУПЛЕНО/{f=1} f&&/^#### Пак/&&!/КУПЛЕНО/{exit} f' docs/PROGRESS.md | command grep -c '^#'`. 3. **Таблицы мутаций нет** — §13 требует полную, выжившие поимённо. 4. **П.9 раздела «Что НЕ удалось» протух:** говорит о четырёх кругах, их семь. 5. **Подозрение b1, оставленное непроверенным:** `repin.go` может дропать помеченного члена c-lite юнита (её м7 и «Что НЕ удалось» п.8). Проверить исполнением или назвать с доводом, почему вне пака. 6. **Нет строки «работа завершена, править не планирую».** 7. **Четыре якоря в ТВОЕЙ зоне сдача b1 сдвинула:** `backend/docs/DISCLOSURE_LAW_DESIGN.md:41–44` (цели — `status.go` ×3 и `bookbuild.go`). Перенавести по ЦЕЛИ: найти, куда уехало то, о чём говорит проза, а не подобрать токен под то, что оказалось на строке (гардрейл `CLAUDE.md`). Хук покажет в этом файле ПЯТЬ битых якорей: пятый, `:40` (`quality.go`), был сломан ещё в `HEAD`, до сдачи. Перенаведи и его тем же способом, но в число сдачи не записывай. Ещё 17 якорей в `docs/` сдача тоже сдвинула — их перенаводит оркестратор при лендинге, не трогать. ## П2. Где лежит работа — и запрет, который здесь дороже обычного - Сдача b1 лежит **ЗАСТЕЙДЖЕННОЙ В ИНДЕКСЕ** рабочего дерева `/home/ubuntu/projects/textmachine-main`: 27 путей (22 M и 4 A в `backend/`, плюс `docs/PROGRESS.md`). Незастейдженных правок в этих путях нет. - **Проверка целостности** (порядок — П4.1): `git -C /home/ubuntu/projects/textmachine-main diff --cached --binary | sha256sum` обязан дать `166997963c95db52f0ba04716017fa2e106ae0596886e29cc918a642afe7df8a`. Бэкап того же патча — `/home/ubuntu/tm-b1-orphan-index.patch`; копия сдачи ТОЛЬКО ДЛЯ ЧТЕНИЯ — `/home/ubuntu/tm-b1-orphan` (дерево `5dbb5cb` с наложенным патчем; корпуса книг и твоих правок в ней нет). - **Авторство видно git'ом:** `git diff --cached -- backend/ docs/PROGRESS.md` — работа b1; `git diff -- backend/ docs/PROGRESS.md` — твои правки поверх неё. Твои НОВЫЕ файлы не видны ни тем, ни другим — перечисли их в отчёте: `git status --short --untracked-files=all -- backend/`. - ⛔ **ИНДЕКС НЕ ТРОГАТЬ:** `git reset` · `git restore` (и `--staged`) · `git stash` · `git checkout -- <путь>` · `git add` · `git clean` — запрещены. Одно неверное движение стирает работу, у которой нет второго исполнителя. - **Ты не коммитишь.** Зона — `backend/` плюс продолжение секции b1 в `docs/PROGRESS.md` (место — П5). - Чужие незакоммиченные файлы вне этого пака не трогай. ## П3. Карта чтения — ЗАКОН 1. `CLAUDE.md` — целиком. 2. Этот промт — раздел ПЕРЕДАЧИ и тело §1–§13. ⚠ `file:line` тела указывают в `HEAD` (`5dbb5cb`), а не в дерево сдачи: адреса уехали (`stagerun.go:204` → `:216`, `:142` → `:160`, `cutcall_test.go:402` → `:451`; `resolvedForResume` уехал ниже в `cutcall.go` и делегирует `FlagReason.AnswersForResume` в `disposition.go`, а прежняя строка `FlagReason(cs.FlagReason) != FlagCancelled` осталась только в `cutoververdict_test.go`). Читай тело через `git show HEAD:<путь>` либо греп-токеном, а не номером. Ссылки тела §3 (`D39.204`, `D2` п.2, ряд 291, кодовые файлы) — справочник предмета, открывай их по мере вопроса, в счёт карты они не входят. 3. Отчёт b1 — `docs/PROGRESS.md`, от `#### Пак «КУПЛЕНО — ЗНАЧИТ ДОСТАВЛЕНО»` до следующего `#### Пак`. Сперва: «Что построено», седьмой круг, «Что НЕ удалось», «Объявляю правки», «Вопросы оркестратору». 4. Сама работа: `git diff --cached --stat` и `git diff --cached -- backend/`. 5. `docs/architecture/12-go-style-notes.md` — только больные места. ## П4. Что делать — разметка свободы **Делай РОВНО так** (отступление — пинг): 1. **Первые действия, в этом порядке:** блок в `/tmp/textmachine-channel` → проверка целостности (П2) → эхо (тело §9) СВОИМИ словами. Хеш не совпал — стоп: до любой правки таблица «ожидал / получил» пингом, а если канала нет — секцией в отчёт, и дальше не идёшь. Отдельной строкой эха: что ты считаешь недоделанным СВЕРХ моих семи пунктов. 2. **Базовая линия в ТВОЁМ дереве до первой правки:** `make battery` из `/home/ubuntu/projects/textmachine-main/backend` (git он не трогает, пишет только в `backend/bin`, корпус книг только читает). ⚠ Мой замер на копии без корпуса дал 9 скипов; в главном дереве корпус есть, и по коду должны побежать ещё пять корпусных пинов (`TestCheckerLabelsCandidates` · `TestCheckerLabelsBaseline` · `TestK6LabelsBaseline` · `TestK6TheTwoRelaxationsPricedSeparatelyOnTheSameLabels` · `TestTheInstrumentAgainstTheColdRunOracle`), так что скипов ожидается 4: `TestMinerFullBookParity` (нет словаря jieba) · `TestCorpusBankKeyConflicts` (не задан `TM_CORPUS`) · `TestHelperEventsRun` и `TestHelperKillLoop` (вспомогательные процессы). Это вывод из кода, не прогон: другое число — не регрессия, но назови его. 3. **Сверка «отчёт ↔ код» в ОБЕ стороны.** (а) Каждая строка таблиц «Что построено» и седьмого круга (С1–С6) — правка ЕСТЬ в коде. (б) Каждый ханк `git diff --cached -- backend/` (75 ханков в 26 файлах) — у него ЕСТЬ строка отчёта (таблицы кругов, «Объявляю правки» п.1–27). Ханк без строки — находка «незаписанная работа», строка без ханка — «записанная, но не сделанная». Обе — в отчёт, не в молчаливую починку. 4. **Мутации — только на КОПИИ.** ⛔ `-root`, указывающий на `/home/ubuntu/projects/textmachine-main/backend`, запрещён: `tmmutate` восстанавливает байты, прочитанные в момент посадки, и затрёт твою правку в том же файле, а убийство процесса по памяти оставит посадку в дереве, которое уедет в лендинг. - подмножество гейта — `make mutations` из `backend/` (229 записей из 440); - **полный каталог** — рецепт цели `mutations` из `backend/Makefile`, развёрнутый в shell, без `-battery` и с `-logs` ВНЕ копии (`trap` удаляет копию на выходе вместе со всем, что внутри). Проверено мною 15.09 исполнением: запись `Z-price-substitution-reports-itself-as-the-answerer` — тем же рецептом встроенной командой (логи в скретчпаде): копия без `.env`, RED; запись `C-verdict-leaves-the-anchored-column` — ДОСЛОВНО этим текстом как файлом-скриптом (`<тег>` подставлен, добавлен `-id`): RED двумя тестами, один из них корпусной оракул `TestTheInstrumentAgainstTheColdRunOracle` (ветка двух корпусных переменных на копии работает), лог вне копии, `TMMUTATE_EXIT=0`, оставленных копий 0, индекс цел. ⚠ `<тег>` замени: с ним как есть `bash -n` падает. Положи в файл вне копии и запусти фоном средствами харнесса, `bash <файл> > <лог> 2>&1; echo "TMMUTATE_EXIT=$?" >> <лог>`, и жди строки `TMMUTATE_EXIT=` в логе, а не уведомления: ``` cd /home/ubuntu/projects/textmachine-main/backend && test -f go.mod \ && [ "$(pwd)" = /home/ubuntu/projects/textmachine-main/backend ] \ && logs=/home/ubuntu/tm-mut-logs-<тег> && mkdir -p "$logs" \ && tmp=$(mktemp -d) && trap 'rm -rf "$tmp"' EXIT && trap 'rm -rf "$tmp"; exit 130' INT TERM \ && mkdir "$tmp/backend" \ && tar -C /home/ubuntu/projects/textmachine-main/backend -cf "$tmp/tree.tar" --exclude='./.env*' --exclude=./bin . \ && tar -C "$tmp/backend" -xf "$tmp/tree.tar" && rm -f "$tmp/tree.tar" \ && TM_CHECKER_LABELS_DIR=/home/ubuntu/projects/textmachine-main/books/gu-zhenren/labels \ TM_RUN_A_DIR=/home/ubuntu/projects/textmachine-main/books/gu-zhenren/door-to-file \ go run ./cmd/tmmutate -root "$tmp/backend" -logs "$logs" ``` Рецепт из шапки `cmd/tmmutate/main.go` как есть НЕ годится: без двух корпусных переменных корпусные пины на копии скипают, скип даёт `exit 0`, и посадка читается выжившей; - одна копия — один мутатор; склейка из нескольких вызовов `-id` законна только при покрытии 440 из 440 без пересечений И при том, что между вызовами дерево не менялось (твоя правка между ними делает склейку негодной); - исходы `tmmutate`: `RED` — поймана · `SURVIVED` — выжила · `survives` — ЗАПИСАННАЯ и аргументированная выжившая (в каталоге 4 такие записи с `expect: survives`, все без `battery`, поэтому видны ТОЛЬКО в полном прогоне — в таблицу отдельной строкой, не в выжившие) · `NOTHING` и `ROTTED` — НЕИЗМЕРЕННЫЕ (в число не кладутся) · `RED!` — запись числилась выжившей и теперь ловится · «NOT GREEN before any mutation» — прогон не состоялся вовсе. Засчитывает мутацию ТЕКСТ падения из `-logs`, а не цвет. Время: полный каталог — больше часа. 5. **Секция «Числа» и таблица мутаций** — написать; каждое число с командой, деревом и популяцией. 6. **П.9 «Что НЕ удалось»** — исправить с пометкой «испр. 15.09». 7. **Финальная строка §13** — по исходу правила остановки (ниже) или по сходимости. **Решаешь сам и аргументируешь** (советы — приоры, опровергаются аргументом или замером): - **Форма восьмого круга.** Узкий круг, вернувшийся чистым, доказывает чистоту ПОСЛЕДНИХ починок, а не сходимость пака. Норма (эррата 04.09-б): круг идёт по дофиксу **против ИСХОДНЫХ пунктов заказа** — здесь дофикс чужой, и тем важнее. Мой приор: один направленный читатель по С1–С6 плюс проход по пунктам тела §4.1–§4.5 против готового дерева. Субагенты разрешены явно; веер и глубину выбираешь ты. ⛔ **Правило остановки — РОВНО так; сам решаешь только, чинить ли найденное до стопа.** Кругов в передаче не больше ДВУХ. Стоп наступает, если (а) любой круг нашёл дефект в починке ПРЕДЫДУЩЕГО круга (седьмого или своего) либо (б) второй круг дал любую НОВУЮ находку. В обоих случаях — таблица «находка → класс → цена» в отчёт и пинг, если канал жив; если канала нет — та же таблица секцией. Финальная строка в этом исходе: **«работа завершена по правилу остановки П4, круги НЕ сошлись — остаток в таблице; править не планирую»**. Лендить ли с названным остатком, решаю я (прецедент — `D39.245` п.1). ## П5. Где эта передача мягкая — и куда писать **Уязвимые места:** 1. ⛔ **Чужие числа.** Все числа отчёта сняты приборами b1 на деревьях своего часа: «каталог 439 записей», «25 = 9 + 3 + 1 + 12», «батарея 23/23» — утверждения автора, а не твоё знание. Её же командой ты повторишь и её ошибку: бери другую популяцию или другую сторону улики. 2. ⛔ **Работа, оборванная на полуслове.** Самая вероятная форма дефекта — починка с одной половиной: комментарий переписан, а пин не заведён; запись каталога заведена, а `find` не уникален; пин заведён, а посадка бьёт не в его слой. У каждой починки седьмого круга спрашивай, где её вторая половина. 3. ⛔ **Изменённые записи каталога, а не только новые.** Кроме 33 новых, сдача изменила 8 записей `HEAD`: у шести — `find` (у одной из них ещё и файл), у двух (`CUTCALL-a-refusal-pays-when-the-reply-outruns-the-write` · `CUTCALL-a-reply-that-outruns-our-own-write-books-zero`) — `run`, расширенный на `TestDeliveryEvidenceIsWhatTheMoneyBitAsks`. Значит, RED посадки §4.5(б) больше не доказывает, что её ловит СКВОЗНОЙ пин — детерминированная таблица поймает за него. Назови по логу, какой тест краснеет. 4. ⛔ **Решения прежнего оркестратора, известные только из отчёта b1.** Переписки с ним нет. Что я подтверждаю и что решаю сам — П6; прочее ратифицированным не считай: наткнёшься — пинг. 5. ⛔ **Зелёная батарея плюс полный каталог сходимостью не являются** — семь кругов этого пака находили дефекты при полной зелени. **Куда писать в `docs/PROGRESS.md`.** Новые подсекции — в КОНЕЦ секции b1, то есть сразу после её «Вопросов оркестратору» и перед следующим `#### Пак`: сперва «ПЕРЕДАЧА 15.09 — план» (замена тела §7, до первой правки), затем круги, «Числа», таблица мутаций, «что не удалось» по передаче. Прежние круги b1 не переписываются (они описывают дерево на свою дату); протухший п.9 правится на месте с пометкой. Строка завершения ставится в ЗАГОЛОВОК секции b1 — так, как у следующей в журнале секции `#### Пак «ЗА ОДНУ ЕДИНИЦУ ПЛАТИМ ДВАЖДЫ»`. Хук якорей при лендинге предупредит о семи якорях отчёта b1 без токена: дописать к ним `=`токен`` РАЗРЕШЕНО, текст не трогая, и токен подбирается по ЦЕЛИ, о которой говорит проза, а не по тому, что оказалось на строке. ## П6. Отмены тела, ответы на вопросы b1 и мои решения **Отменено в теле (раздел сильнее). Носитель — «Эррата 15.09-а» в шапке `docs/architecture/05-decisions-log.md`:** - Слово владельца 11.09 (цитата — тело §4.1): отказ резервации на ретрае — СТАНДАРТНАЯ ОСТАНОВКА. У `D39.204` сняты: в п.4 — деградация во флаг, отгрузка текста и продолжение волны; п.5 (а)–(б); в п.5 (в) — пин «купленное доставлено ⇒ не `exit 4`». ОСТАЁТСЯ требование п.4, чтобы причина отличалась от исчерпания регенераций, — на нём стоит `retry_unaffordable` и комментарий сдачи, ссылающийся на «D39.204 п.4». По этим расхождениям тела с журналом не пинговать. - Тело §2, фраза «её половина едет ОТДЕЛЬНЫМ промтом», и последнее предложение §4.4 («я передам это платформенной сессии, и акт будет один») — сняты: платформенная половина пуста по замеру b1 (§4.4 её отчёта), отдельного платформенного промта не будет, акт один. Обязательство ряда 291 «зеркало двух зон» закрывается этим замером. - Тело §7 — заменено (П5). Пункты «решаешь сам» §4.1 уже решены b1 и без находки пере-решению не подлежат. **Ответы на «Вопросы оркестратору» b1:** 1. Ряды контракта 14 — их не хватает ТРИ (`retry_unaffordable` · `cancelled` · `attempt_timeout`; канон говорит «Причин шестнадцать», в `flagSeverity` 19 ключей) — моя зона, делаю при лендинге. Не трогать. 2. Расхождение витрин `status` и экспорта на одной строке — ряд бэклога заведу я при лендинге. 3. Вторая дверь невидимой дыры (позиция, чья единственная трата — сожжённый ключ, метки не получает) — вопрос владельцу, несу я. В этом паке не строится. 4. Третья читательская фраза («оплачено, но не доделано: пополните и перезапустите») — вопрос владельцу, несу я. Ветку не трогать: она готова принять строку данных. 5. Ось «эхо только по отгруженному тексту» (`D39.18`, открытое решение владельцу) — абзац «чтение, которое берёт код» оставить как есть. 6. Переименование `echo_edit_units` → `echo_edit_rows` — **в этом паке НЕ делается:** правка опубликованного ключа потребовала бы нового круга по пакету, который ты сводишь, а читателей вне `backend/` у ключа ноль и на исполнимых конфигах числа совпадают. Оговорка у поля остаётся, ряд бэклога заведу я. 7. Анкор техдолга в `docs/architecture/13-tech-debt-anchors.md` — моя зона. **Три просьбы b1 к оркестратору, которых нет среди её «Вопросов», — исход:** 8. Смена смысла эхо-метрики на эдит-волне (её Т1 и «Что НЕ удалось» п.7) — **решаю при приёмке**, сессия не трогает. 9. Расщепление `withheld_units` на «нужны деньги» и «нужен человек» (её М5) — контракт двух зон; ряд бэклога заведу я. 10. Ранг новой причины 4 вместо 8, стоящий на существующем пине `TestTheSeverityTableMeansWhatItsCommentsSay` — **решаю при приёмке**, сессия не пере-решает. **Подтверждаю** решения прежнего оркестратора, на которых стоит построенное: (а) новый РОД дыры не заводится — довод о пяти счётчиках платформы (`platform/internal/ingest/build.go`); (б) выбор читательской фразы спрашивает предикат вердикта, а причина остаётся на записи дыры; (в) платформенная половина пуста — см. отмены выше. ## П7. Среда этой машины (15.09, а не прошлой) - `/tmp` здесь — ext4 на общем диске, не tmpfs. Место проверяй командой `df -h /tmp` рядом с итогом тяжёлого прогона, а не числом отсюда: `no space left on device` даёт красное, неотличимое от дефекта кода. - Тулчейн: go 1.26.7, golangci-lint 2.12.2 (пин — 2.12.2). - ⛔ Перед тяжёлым прогоном — `cat /proc/self/cgroup` и `memory.max` этого cgroup (гардрейл `CLAUDE.md` про `CONSTRAINT_MEMCG`). У моего процесса потолка нет, у твоего может быть. Сужать мутационный прогон через `-run`, чтобы влезть в память, нельзя. ## П8. Остальное — по телу §5 · §6 · §8 · §9 · §10 · §11 (канал вопросов, право отказаться, тесты не под зелень, старший коллега Fable 5 — один на сессию) · §12 · §13 действуют и адресованы тебе, с заменами из П4–П6. **Адрес оркестратора** — блок `role=оркестратор` в `/tmp/textmachine-channel`, сверенный с `ListAgents`; ⚠ `textmachine-main-b1` в списке — пустая сессия владельца, а НЕ сессия b1, и сессия `textmachine-11` из шапки тела мертва. Нужной роли в файле нет ⇒ канала нет: вопросы секцией отчёта, работа продолжается (исключение — стоп по хешу, П4.1). --- # Бэкенд-пак: КУПЛЕНО — ЗНАЧИТ ДОСТАВЛЕНО. Юнит, который не доделается НИКОГДА > Выдан оркестратором №23 (сессия `textmachine-11`) 11.09. Пак **$0** — платных вызовов в нём нет. > Предмет решён владельцем 05.09 (`D39.204`); ты строишь решённое, а не выбираешь между вариантами. ## 1. Какая проблема и что решит твой результат Читатель заплатил за главу. Движок купил первую попытку, получил флагуемый результат, пошёл за второй — и **вторую ему не продали**: потолок книги или дня не вмещает резерв регенерации. ⚠ **И тут точность несущая, первая редакция промта её теряла:** `maxTokensForAttempt` удваивает **только ВЫХОДНОЙ** бюджет, а резерв считается оценкой по цене, промпту, потолку и буферу размышления (`backend/internal/pipeline/stagerun.go`, греп `EstimateUSD`) — промпт и аддитивный буфер НЕ удваиваются. Значит «попытка 1 стоит ×2» — неправда, и окно, в котором отказ неизбежен на ≥1 и невозможен на 0, считается по РЕАЛЬНОЙ оценке. Дальше происходит вот что, и это проверяется одной строкой: **`backend/internal/pipeline/stagerun.go:216`=`infra failure; the cancelled-position mark`** — ЛЮБАЯ ошибка попытки уходит наверх из цикла, **РАНЬШЕ `UpsertChunkStatus`**. **Следствия два, и оба стоят денег читателя:** 1. **Юнит не доделается НИКОГДА.** Чекпойнт попытки 0 есть (реплей за $0), строки `chunk_status` НЕТ ⇒ читающие модели видят юнит как `pending`, экспорт не отдаёт ничего. Каждый резюм реплеит попытку 0 за $0 и умирает на попытке 1. **Прогон уходит `exit 4` при ПОЛНОСТЬЮ доставленных купленных юнитах.** 2. **Волну нельзя продолжить без ДЫРЫ в непрерывном префиксе** — то есть за это платят и соседние юниты, которые в бюджет влезали (разброс резервов внутри волны замерен ×2.976). **Решение владельца (`D39.204`, и оно НЕ обсуждается):** отказ резервации на РЕТРАЕ **деградирует во ФЛАГ**, причина которого ОТЛИЧНА от исчерпания регенераций; текст попытки 0 оплачен и **отгружается**; волна идёт дальше. ⛔ Вариант «минимальная покупка ≥ `step_max_usd`» **СНЯТ** владельцем — он стоил бы покупателю входного порога в пять глав. Не реализуй его и не предлагай. ⚠ **И канон здесь сильнее, чем кажется:** `D2` п.2 уже ТРЕБУЕТ тегировать `flag_reason`. Значит новая причина — не добавка к контракту, а его ИСПОЛНЕНИЕ. (Ссылка «смена `D2.3`», гулявшая по бэклогу, **неверна дважды**: `D2` и так кончается флагом, а `D2.3` — про детектор вырождения перед удвоением.) ## 2. Зона записи и git - Зона — **`backend/`**, и только она. `platform/` не трогать: её половина едет ОТДЕЛЬНЫМ промтом, но **ОДНИМ АКТОМ с твоим** (см. §4.3). - **Ты не коммитишь.** Готовое дерево передаёшь мне, я лендлю. `git add -A` запрещён каноном. - Свою секцию итогов пиши в `docs/PROGRESS.md` — это единственное исключение из «`docs/` — зона оркестратора». Чужие незакоммиченные файлы в дереве не трогай. ## 3. Карта чтения — ЗАКОН, дальше только по её ссылкам 1. `CLAUDE.md` — целиком. 2. **Тело `D39.204`** в `docs/architecture/05-decisions-log.md` (решение владельца) и **`D2` п.2** — он в закрытой эре, тело в `docs/archive/architecture/05-decisions-D1-D38.md`, греп `^## D2\.`. ⚠ Подномер собственного тела не имеет: `D2.3` — это ПУНКТ 3 тела `D2`. 3. **Ряд 291** в `docs/BACKLOG.md` — там весь разбор, включая **опровергнутую посылку прошлого оркестратора**: «ретрай оставляет ФЛАГОВАННЫЙ юнит» — ЛОЖЬ, зона опровергла по строкам. Не наступи второй раз. 4. `backend/internal/pipeline/stagerun.go` (цикл попыток и `runAttempt`), `escalation.go` (`errReserveCeiling` и кто на нём УЖЕ деградирует), `disposition.go` (словарь `FlagReason`). 5. `docs/architecture/12-go-style-notes.md` — нормативы стиля, только больные места. Код-факты добывай сам; `file:line` выше — отправные точки. **Код первичен.** ## 4. Состав ### 4.1 ⛔ КОНСТРУКЦИЯ ПЕРЕ-РЕШЕНА ВЛАДЕЛЬЦЕМ 11.09 — читай это ПЕРЕД кодом **Слово владельца дословно:** «Надо о таком просто сообщать в виде метаданты, которая сейчас и пишется предупреждением, и иметь возможность поднять просто потолок и возобновить прогон, так как **это ситуация всё же СТАНДАРТНАЯ СО СТОПОМ, просто он произошёл по какой-то другой причине**». ⛔ **Это отменяет обе половины прежнего заказа — и моего, и `D39.204` п.4.** Ни «деградировать во флаг», ни «волна идёт дальше» больше НЕ строится. Прежний план заводил новый исход; новый — **возвращает ситуацию в УЖЕ ПОСТРОЕННЫЙ штатный путь остановки**, из которого она сегодня выпадает. **Что это значит механически (моё чтение; спорь, если код скажет иначе):** 1. **Прогон ОСТАНАВЛИВАЕТСЯ, как при любом отказе по потолку.** Не продолжается с флагом. ⭐ И это заодно снимает то, чем ряд 291 пугал: «продолжить волну нельзя без ДЫРЫ в непрерывном префиксе» — при остановке дыры не возникает вовсе. 2. **Отказ ретраю публикует ту же метадату, что и любая остановка по потолку** — кадр `Ceiling{Halted, Scope, ShortfallMicroUSD}` (`backend/internal/runevents/runevents.go`, греп `ShortfallMicroUSD`). ⭐ **Он уже несёт ровно то, что владелец просит:** «пополни хотя бы на столько, и тот же вызов будет допущен» — и это **ратифицировано им же, `D39.203`**. Строить новый носитель не надо. ⚠ **И твоя находка №2 этим РАЗРЕШАЕТСЯ, а не отменяется:** ты была права, что `ceilingReached` идемпотентен по прогонному флагу и съел бы событие настоящей остановки — но теперь съедать НЕЧЕГО: эта остановка И ЕСТЬ настоящая. Публикуй через штатный путь. 3. ⛔ **НАСТОЯЩИЙ ДЕФЕКТ — УЖЕ, чем я написал, и он назван в самом дереве.** Механизм «отметить остановленную позицию» построен ИМЕННО против невидимых дыр: `backend/internal/pipeline/stagerun.go:160`=`THE MARK FOR A STOPPED POSITION IS ATTACHED TO EVERY EXIT`, и его комментарий приводит замер прежнего инцидента — «прогон, остановленный на эскалационном хопе, рассчитал деньги и не оставил строки вовсе: `committed=0.001176`, `chunk_status_rows=0`». **Но метка — no-op для всего, что не «доставленный вызов, который остановил человек»** (`recordCancelledStage`). Отказ по потолку под это не подпадает ⇒ юнит остаётся без строки. **Вот дыра, и вот что ты закрываешь.** 4. **Поднял потолок → резюм ДОДЕЛЫВАЕТ юнит.** Значит строка, которую ты пишешь, обязана быть НЕ-ТЕРМИНАЛЬНОЙ для резюма — по образцу `FlagCancelled`, единственной причины, у которой `resolvedForResume` ложен (`backend/internal/pipeline/cutcall.go:293`=`FlagReason(cs.FlagReason) != FlagCancelled`), и ложен именно потому, что это «оплачено, но не сделано». Твой случай той же природы. **Делай РОВНО так:** остановка штатная · метадата через уже построенный кадр с недостачей · **юнит получает строку, а не пустоту** · строка НЕ терминальна для резюма · после пополнения резюм доделывает. **Решаешь сам и аргументируешь:** как назвать причину в строке юнита (или взять существующую) · где ставится метка · как отличить «остановлено на ретрае» от «остановлено на попытке 0» в носителе, и надо ли отличать. ⛔ **Попытку 0 не трогать:** её отказ и сегодня останавливает книгу штатно — ратифицировано. ⛔ **КТО ПЛАТИТ — НЕ ПРЕДМЕТ ЭТОГО ПАКА.** Слово владельца 11.09: «пока платит за всё ЮЗЕР, потом будем решать эту проблему». Механизм «платит продукт» не строить; существующее биллинговое поведение не трогать ни в какую сторону, даже где оно выглядит непоследовательным. ⚠ И отдельной строкой отчёта НАЗОВИ (не чини): объёмный леджер сегодня считает флагованный юнит НЕ доставленным, то есть грант за него не съеден — это расходится со словом владельца и существует ДО твоего пака. Он объявил вопрос отложенным. ⚠ **Отгрузка обрезанного текста не строится** — `D2` запрещает отгружать загрязнённое, и это не зависит от того, кто платит. ### 4.2 Пин, ради которого пак существует **«ОСТАНОВКА, КОТОРАЯ ЛЕЧИТСЯ ПОПОЛНЕНИЕМ».** Три утверждения, и они про разное: 1. **Юнит, на ретрае которого отказал потолок, ПОЛУЧАЕТ СТРОКУ.** Сегодня её нет — это и есть невидимая дыра. Пин обязан печатать величину, доказывающую, что деньги были потрачены, а строка появилась: пустой `chunk_status` рядом с ненулевым `committed` — ровно тот замер, которым дерево описывает прошлый инцидент. 2. **Остановка несёт НЕДОСТАЧУ.** `ShortfallMicroUSD` ненулевой и таков, что пополнение на него допускает тот же вызов. ⚠ Пин на «событие вообще есть» вырожден — утверждай ЧИСЛО. 3. **Пополнил потолок → резюм ДОДЕЛАЛ юнит.** ⛔ **И это ГАРД, а не доказательство лечения — поправка исполняющей сессии, принята.** Моё «сегодня второй прогон умирает вечно» НЕВЕРНО: строки у юнита нет ⇒ гейт резюма не срабатывает ⇒ позиция ре-атакуется, попытка 0 реплеится из чекпойнта за $0, ретрай покупается, и при поднятом потолке юнит доделывается **уже сегодня, без пака**. Вечно умирает только резюм БЕЗ пополнения. ⇒ этот пин стережёт ратифицированное `D4`, чтобы пак его не сломал, и **на дефекте он ЗЕЛЁН**. Так и напиши. ⛔ **И отсюда норма приёмки этого пака, которой у нас ещё не было ни в одном:** сними ЦВЕТ КАЖДОГО из трёх пинов на дереве **ДО** фикса, числом, и положи замер в отчёт. На дефекте краснеет только первый. «Пин зелен» и «пин стережёт» — разные утверждения, и без этого замера они сливаются. ⚠ **Про коды выхода.** Прежняя редакция промта требовала `exit 2` вместо `exit 4`. **Снято:** при штатной остановке код остаётся тем, каким он и был для остановки по потолку. Предмет пака — не смена кода выхода, а то, что за ним стоит: **строка вместо пустоты и лечимость пополнением.** ⚠ **Два гейта поймают тебя сами — назову, чтобы не терять круг:** `TestEveryFlagReasonIsRanked` потребует завести новую причину в `flagSeverity` (`backend/internal/pipeline/status.go`), если ты её заводишь, а `TestEveryOperatorMessageIsCatalogued` — внести новое сообщение в `backend/internal/pipeline/testdata/operator-messages.txt` (сегодня в каталоге 134 строки, из них о потолке уже говорят четыре — посмотри их прежде, чем писать пятую). ### 4.3 ⛔ ДЕФЕКТ, КОТОРЫЙ ТВОЙ ПАК НАКОРМИТ — и он НЕ латентный. Чинить ЗДЕСЬ Нашла исполняющая сессия, посылку я пере-проверил и **она у неё неверна в СТОРОНУ МЯГКОСТИ**. `backend/internal/pipeline/quality.go` (греп `draftEchoRecovered`) считает эхо ВОССТАНОВЛЕННЫМ по одному признаку — `FirstFlagReason == cjk_artifact`, — **не спрашивая, флагована ли строка сейчас и чем**. Денежный отказ эхо-рероллу даст ровно эту картину: первый флаг — эхо, итоговый — денежный, реролла не было, а отчёт скажет «восстановлено». ⛔ **Сессия назвала это латентным «потому что ключ 0». Ключ НЕ ноль:** `regenerate_echo_before_escalate: 1` стоит **во всех ЧЕТЫРЁХ боевых конфигах** (`backend/configs/pipeline-c1.yaml`, `-c2`, `-arm-glm`, `-arm-mistral` — сверено мною по каждому). ⇒ дефект оживает **в день лендинга твоего пака**, а не когда-то потом. **Чини его в этом паке и пинь** — «диспозиция в отчёте» здесь недостаточна. ### 4.4 Платформенная половина — **твоё дело назвать, не построить** Карта заметок платформы **РУКОПИСНАЯ** (`platform/internal/ingest/notes.go`) и уезжает независимо от словаря движка. Цена несделанного **замерена**: `PD-246` — минор 0.10.0 сутки жил ЛОЖНЫМ на проводе, причина доезжала читателю как `unspecified`, и поймала это зона своей пере-проверкой ПОСЛЕ слов оркестратора «приёмка закончена». ⇒ **отдельным пунктом отчёта** назови мне: точное значение новой причины на проводе · что платформа обязана записать прогону, который кончился флагом вместо `exit 4` · какой её пин это стережёт. Я передам это платформенной сессии, и **акт будет один на две половины**. ⚠ **И следствие, которое стоит назвать сразу, потому что оно про деньги читателя:** объёмный леджер считает флагованный юнит НЕ доставленным (`backend/internal/pipeline/volume_test.go`, греп `TestAFlaggedUnitIsNotReportedAsDelivered`). Значит грант за него не съеден, а книга честно короче — это хорошая новость, но она обязана быть СКАЗАНА в отчёте, иначе следующая смена откроет её заново. ### 4.5 Приложение — ДВА пина, краснеющих по УДАЧЕ (ряд 379, ОБЕ половины) Отдельная от §4.1 работа; делай её ПОСЛЕ основной. ⛔ **И мой диагноз здесь был НЕВЕРЕН — опровергнут замером, а не мнением. Читай, чем именно, иначе повторишь мою ошибку.** **Половина (б).** Запись каталога `CUTCALL-a-refusal-pays-when-the-reply-outruns-the-write` стережёт самую дорогую половину денежного бита `delivered()` (`backend/internal/llm/attemptcut.go:189`=`answered && t.firstByte.Load()`): провайдер ОТКАЗЫВАЕТ и рвёт коннект, пока наше тело ещё пишется — байт ответа есть, статуса в руках нет, и чтение «байт = доставка» оплачивает сметой каждый отказ (замер прежнего пака: 22 отказа из 25, один на $0.80). **Два независимых замера на посадке (снятие `answered &&`), и они расходятся:** мой — **7 красных из 8** (снят на нагруженной машине, рядом шла батарея); опровергателя на спокойной — **8 из 8**, а на сорока процессах **39 FAIL / 1 PASS**. ⇒ пин краснеет по УДАЧЕ, это подтверждено обоими; частота зависит от нагрузки, и поэтому «восемь красных подряд» **не является критерием приёмки**: сегодня, без единой правки, восьмёрка выпадает примерно в 82 случаях из 100. ⛔ **А вот ПРИЧИНА не та, что я написал.** Я заказывал «сделать приход байта ответа НЕИЗБЕЖНЫМ до обрыва». Зонд опровергателя (40 итераций, печать того, что реально получил клиент) дал **39 × обрыв с отказом записи и 1 × ПОЛНЫЙ `401`**, и ни разу — «ни куска, ни статуса». То есть байт приходит практически всегда, а мутант выживает в ДРУГОМ случае: клиент успевает вычитать `401` ЦЕЛИКОМ, `Do` возвращает не ошибку записи, а ОТВЕТ, и `delivered()` не спрашивают вовсе — ошибка уходит статусной веткой. **Моё лекарство било по половине, которая и так держится, и увеличивало вероятность ровно того исхода, в котором мутант выживает.** (И «~6 МБ тела» тоже неверно: 11.0 МБ — Go не эскейпит кириллицу в JSON.) **Задача — делай РОВНО так в части ЧТО, способ твой:** 1. **Тест утверждает СВОЮ ПОСЫЛКУ и печатает её:** что `Do` вернул ошибку ЗАПИСИ и что трасса видела первый байт. **Сценарий не состоялся ⇒ тест КРАСНЫЙ**, а не зелёный «мимо предмета». Сегодня он зелен и на полном `401`, то есть на другом предмете. 2. **Прямой табличный пин на сам `delivered()`** — он убивает посадку `answered &&` детерминированно, без гонки вообще. 3. ⚠ У фикстуры `MaxAttempts: 3` — до трёх бросков кости на один `Complete`; **границу утверждай ПО ПОПЫТКЕ**, а не по итогу вызова. **Половина (а) — её первая редакция промта не заказывала вовсе.** Тот же ряд 379 несёт вторую половину: две строки таблицы девяти в `backend/internal/pipeline/cutcall_test.go:451`=`time.Sleep(50 * time.Millisecond)` разводятся ОКНОМ СТЕННЫХ ЧАСОВ, и по какую сторону границы заголовков сел `cancel()`, не утверждается ничем — замер приёмки дал **2 красных из 8**. **Ряд закрывается ТОЛЬКО вместе с этой половиной.** ⛔ **Критерий приёмки берётся из самого ряда 379, он сильнее моего:** «каждый из двух пинов **ПЕЧАТАЕТ величину, доказывающую пройденную границу, и ПАДАЕТ, когда сценарий не состоялся»**. ## 5. Где этот пак мягкий — четыре места, назвал я, веер и глубину выбираешь ты Мандат самопроверки — **исполнением**; субагенты разрешены явно. Адверсариальный проход по СВОЕЙ ГОТОВОЙ работе обязателен. 1. ⛔ **Пин, утверждающий только молчание, вакуумен ровно там, где сообщение ложно.** «Ошибка не вышла наверх» — утверждение о молчании. Фикстура обязана быть такой, где новая причина ОБЯЗАНА прозвучать, и тест утверждает её ИМЯ. 2. ⛔ **Фикстура обязана сделать отказ резервации НЕИЗБЕЖНЫМ на попытке ≥1 и НЕВОЗМОЖНЫМ на попытке 0** — и окно считается по РЕАЛЬНОЙ оценке резерва, а не по «×2» (см. §1). Денежный пин, флейковый на мутанте, измеряет пустой сценарий: у нас уже был пин, дававший 2 красных из 8, потому что деньги были ВЕРОЯТНЫ, а не неизбежны. Гоняй свой не один раз. 3. ⛔ **Посадка обязана бить в тот же слой, что стережёт пин.** За прошлый пак мутация трижды оказалась не про то: недостижимое условие в фикстуре · не собирающаяся посадка (НЕизмеренная — хуже выжившей) · код против гейта над данными. 4. ⛔ **Новая причина — факт ПРОВОДА, а не словаря.** Тест, проверяющий только, что константа добавлена в `FlagReason`, не доказывает, что читатель её увидит. Скажи, чем предъявлена дорога от флага до отчёта/экспорта. ⚠ И общее, стоившее трёх смен подряд: **зелёная батарея плюс полный мутационный каталог сходимостью НЕ являются.** В последних трёх паках направленный второй читатель находил 6, 7 и 9 дефектов при полной зелени. ### ⭐ Адверсариальная стойка — способ смотреть, не правило пака - ⛔ **Автор и ревьюер — разные роли, даже когда это один ты.** Перечтение своей работы рубежом не считается: поднимай читателя, которому НАЗВАНО, где мягко. - ⛔ **Спрашивай у аномалии, о ЧЁМ она — о предмете или о твоём приборе.** - ⛔ **Верный результат при неверном методе не краснеет нигде.** «Сошлось» — не доказательство. - ⛔ **Утверждение о молчании вакуумно** без фикстуры, где оно ОБЯЗАНО прозвучать. - ⛔ **Заимствованное число проверяется не на существование, а на ТУ ЛИ КЛЕТКУ:** та же роль, та же модель, та же стадия, тот же режим? - ⭐ **Главный вопрос отчёта — не «что не получилось», а «что ты знаешь и не сказала».** ### ⭐ Находки ВНЕ заказа — отдельный заказ владельца Слово владельца 11.09: **находить проблемы даже там, где мы не ждём.** Задавай себе в каждой фазе вопрос, у которого нет заранее известного ответа: **что здесь стоит дороже, работает хуже или ведёт себя страннее, чем должно бы, — и о чём никто не спрашивал?** Ради чего он заведён: удорожание из-за падающих запросов на НАШИХ настройках никто не искал — просто кто-то посмотрел в леджер без гипотезы и увидел 25.4 % цены книги в выброшенных попытках, при зелёных тестах и молчащих гейтах. **Докладывай отдельной секцией: криты · мажоры · регрессии · баги · жёсткие точки улучшения** — каждое аргументированно, с носителем (`file:line`, число, команда) и с ценой в деньгах, тексте или доверии читателя. ⚠ Секция обязана быть непустой ИЛИ нести строку «искал вот так, не нашёл» с перечислением мест: «находок нет» и «не смотрел» в отчёте выглядят одинаково. ## 6. Предметные оси ревью Выбери 1–3 и назови какие. Мой приор: **деньги под гонкой** · **терминальное состояние прогона** (что видит платформа и что видит человек) · **обратная совместимость словаря причин**. ## 7. Записка-план ДО работы Перед первой правкой — записка: что меняешь, чем предъявишь, где ждёшь сопротивления. Комплектность против заказа сверяй механически. ## 8. Заявление = команда Каждое число и каждая категорика отчёта — **с командой, которой получены**. Дифф `^func Test` — **исполнением, не памятью**. Приёмка пере-снимает. ⛔ **И три нормы кодового пака, каждая ловит свой класс:** - **перед отчётом сверь КАЖДЫЙ клейм с результатом инструмента ЭТОЙ сессии** — не с памятью о прогоне; - **последний абзац отчёта оказался планом или обещанием? Сделай его СЕЙЧАС** — обещание в отчёте не переживает смены; - **в длинной сессии — интервальная самоверификация субагентом против ЯВНЫХ критериев** (`D39.121`), а не в конце: проверка, отложенная до сдачи, проверяет уставшую работу уставшим взглядом. ## 9. Эхо-протокол старта **Порядок двух первых действий:** сперва впиши свой блок в `/tmp/textmachine-channel` (§12), потом отправь эхо — эхо без блока некуда адресовать. **Эхо** — ≤10 строк СВОИМИ словами: что понял · что считаешь опасным · что считаешь неверным. Не пересказ: дословный пересказ подтверждает канал, но не понимание, и ошибку промта повторяет вместе с ним. **Адрес бери из `/tmp/textmachine-channel`** — блок с `role=оркестратор`, — а не из этого промта: имя сессии не переживает рестарт окружения. Перед отправкой сверься с `ListAgents`: файл переживает смерть сессии, а `ListAgents` — нет. ## 10. Что НЕ удалось — обязательная секция отчёта И вторая её половина: **«где прибор слеп и я это знаю»** — что невидимо · почему не чинил · чем закрывается. ⭐ Норма прошлой смены: **«в коде названо, в отчёте нет — значит для следующей смены НЕ названо».** ## 11. Канал вопросов и право отказаться Конфликт промта с кодом или доками — **пинг мне, не интерпретация**. Право сказать «этого делать не надо» с аргументом у тебя есть и им пользовались: в двух случаях из трёх правы были сессии, а не я. ⛔ **Тесты и гейты под зелень не подгонять.** Правка, вызванная ЗАКАЗАННОЙ сменой поведения, — обслуживание, и протухший тест держать не нужно; но она **ОБЪЯВЛЯЕТСЯ** в отчёте: что изменилось, какой тест это описывал, куда уехала гарантия. ### ⭐ Старший коллега — Fable 5. **Разрешён ОДИН на сессию (слово владельца 11.09)** У тебя есть право поднять **одного** агента на модели **`fable`** и держать его как СОВЕТЧИКА при сомнениях — тем же способом, каким это делает оркестратор. Владелец разрешил ровно одного на сессию. **Как с ним работать, и форма здесь важнее числа:** - **Поднимаешь ОДНОГО и держишь его весь пак.** Ценность этого агента — в НАКОПЛЕННОМ контексте смены: он помнит, что ты уже решил и почему. ⛔ **Второго не поднимай** — вопросы ДОСЫЛАЮТСЯ первому (`SendMessage` по его id), а не адресуются свежему. Свежий агент вместо накопленного — потеря именно того, ради чего он заведён. - **Модель задавай ЯВНО** (`model: "fable"`), иначе она унаследуется и ты не будешь знать, что у тебя работает. - **О чём его спрашивать:** сомнение в решении · развилка, где оба пути выглядят законными · «не заказываю ли я уже построенное» · «не противоречит ли это ратифицированному» · спорная формулировка в отчёте. ⚠ **Спрашивай С КОНТЕКСТОМ и со СВОЕЙ рекомендацией** — вопрос без твоего варианта ответа даёт совет ни о чём. - ⛔ **Он советчик, а не источник истины: его ответ проверяется деревом.** У оркестратора он за смену ошибся дважды на фактах (называл платный прогон бесплатным, объявлял ряд новым предметом) — и оба раза его ВЫВОД оставался верным. Проверяй посылки, принимай выводы по существу. - **Что он дал оркестратору за эту смену** — для калибровки, чего от него ждать: поймал, что я собирался завести новый ряд бэклога под предмет, у которого ряд уже был; развернул порядок паков доводом, который я не назвал; и назвал условие, без которого два прогона стали бы несравнимы. ## 12. Прямой канал Механизм — `CLAUDE.md` §«Связь между сессиями». Впиши свой блок в `/tmp/textmachine-channel` ПЕРВЫМ действием. Нужной роли нет ⇒ канала нет, и это нормальный случай: НЕ опрашивай сессии подряд. ## 13. Критерий завершённости У каждого пункта заказа — исход (сделано · не делаю с доводом · пинг) · круги СОШЛИСЬ (последний не дал НОВЫХ находок; прежние закрыты таблицей «находка → что сделано → ЧЕМ ПРЕДЪЯВЛЕНО») · **таблица мутаций полная, выжившие названы, и КАЖДАЯ новая запись помечена `battery`** (прошлый пак этого не сделал, и его «21/21 RED» оказался разовым прогоном смены, а не гейтом проекта) · числа сняты ПОСЛЕ последней правки · всё живое в ДЕРЕВЕ, а не в письме · явное **«работа завершена, править не планирую»**. Без последнего пак считается идущим.