20 KiB
Бэкенд-пак: КУПЛЕНО — ЗНАЧИТ ДОСТАВЛЕНО. Юнит, который не доделается НИКОГДА
Выдан оркестратором №23 (сессия
textmachine-11) 11.09. Пак $0 — платных вызовов в нём нет. Предмет решён владельцем 05.09 (D39.204); ты строишь решённое, а не выбираешь между вариантами.
1. Какая проблема и что решит твой результат
Читатель заплатил за главу. Движок купил первую попытку, получил флагуемый результат, пошёл за второй — и
вторую ему не продали: потолок книги или дня не вмещает удвоенный бюджет регенерации
(maxTokensForAttempt удваивает на каждой, значит попытка 1 резервирует вдвое больше попытки 0).
Дальше происходит вот что, и это проверяется одной строкой: backend/internal/pipeline/stagerun.go:204=infra failure; the cancelled-position mark — ЛЮБАЯ ошибка попытки уходит наверх из цикла, РАНЬШЕ UpsertChunkStatus.
Следствия два, и оба стоят денег читателя:
- Юнит не доделается НИКОГДА. Чекпойнт попытки 0 есть (реплей за $0), строки
chunk_statusНЕТ ⇒ читающие модели видят юнит какpending, экспорт не отдаёт ничего. Каждый резюм реплеит попытку 0 за $0 и умирает на попытке 1. Прогон уходитexit 4при ПОЛНОСТЬЮ доставленных купленных юнитах. - Волну нельзя продолжить без ДЫРЫ в непрерывном префиксе — то есть за это платят и соседние юниты, которые в бюджет влезали (разброс резервов внутри волны замерен ×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. Карта чтения — ЗАКОН, дальше только по её ссылкам
CLAUDE.md— целиком.- Тело
D39.204вdocs/architecture/05-decisions-log.md(решение владельца) иD2п.2 — он в закрытой эре, тело вdocs/archive/architecture/05-decisions-D1-D38.md, греп^## D2\.. ⚠ Подномер собственного тела не имеет:D2.3— это ПУНКТ 3 телаD2. - Ряд 291 в
docs/BACKLOG.md— там весь разбор, включая опровергнутую посылку прошлого оркестратора: «ретрай оставляет ФЛАГОВАННЫЙ юнит» — ЛОЖЬ, зона опровергла по строкам. Не наступи второй раз. backend/internal/pipeline/stagerun.go(цикл попыток иrunAttempt),escalation.go(errReserveCeilingи кто на нём УЖЕ деградирует),disposition.go(словарьFlagReason).docs/architecture/12-go-style-notes.md— нормативы стиля, только больные места.
Код-факты добывай сам; file:line выше — отправные точки. Код первичен.
4. Состав
4.1 Деградация — делай РОВНО так в ЧАСТИ РЕШЕНИЯ, сам решай КАК
Ровно так (решено владельцем, отступление = пинг):
- отказ резервации на попытке ≥1 при существующем оплаченном результате попытки 0 ⇒ флаг, а не ошибка наверх;
- у флага СВОЯ причина, отличная от исчерпания регенераций: читатель и оператор обязаны отличать «мы перепробовали всё» от «денег не хватило на вторую попытку»;
- текст попытки 0 отгружается;
- волна идёт дальше.
Решаешь сам и аргументируешь: имя причины · где именно ставится деградация (в цикле runStage или
внутри runAttempt — у обоих есть довод, назови свой) · как при этом НЕ тронуть попытку 0: её отказ
по-прежнему ОСТАНАВЛИВАЕТ книгу, это ратифицировано и менять нельзя (stagerun.go, греп mandatory).
⚠ Гипотеза, которую надо ПРОВЕРИТЬ, а не принять: деградация сама по себе закрывает и следствие (2) — у юнита появляется статус, значит дыры в непрерывном префиксе нет. Похоже на правду; предъяви замером.
4.2 Пин, ради которого пак существует
«Купленное доставлено ⇒ не exit 4». Прогон, где каждый купленный юнит доставлен, а один из них
доставлен ФЛАГОВАННЫМ из-за нехватки денег на ретрай, обязан кончиться успехом, а не кодом 4.
⛔ И пин на саму незаклиниваемость: после такого прогона резюм не делает НИ ОДНОГО свежего платного вызова по этому юниту и не умирает. Сегодня он умирает вечно.
4.3 Платформенная половина — твоё дело назвать, не построить
Карта заметок платформы РУКОПИСНАЯ (platform/internal/ingest/notes.go) и уезжает независимо от
словаря движка. Цена несделанного замерена: PD-246 — минор 0.10.0 сутки жил ЛОЖНЫМ на проводе, причина
доезжала читателю как unspecified, и поймала это зона своей пере-проверкой ПОСЛЕ слов оркестратора
«приёмка закончена».
⇒ отдельным пунктом отчёта назови мне: точное значение новой причины на проводе · что платформа обязана
записать прогону, который кончился флагом вместо exit 4 · какой её пин это стережёт. Я передам это
платформенной сессии, и акт будет один на две половины.
4.4 Приложение — фикстура, краснеющая по УДАЧЕ (ряд 379(б))
Отдельная, маленькая и не связанная с §4.1 работа; делай её ПОСЛЕ основной.
Запись каталога CUTCALL-a-refusal-pays-when-the-reply-outruns-the-write стережёт самую дорогую половину
денежного бита delivered() (backend/internal/llm/attemptcut.go:189=answered && t.firstByte.Load()). Замер оркестратора 11.09: на
чистом дереве пин TestARefusalIsNotAPurchaseEvenWhenTheReplyOutrunsTheWrite даёт 8 зелёных из 8, на
своей посадке — 7 КРАСНЫХ ИЗ 8, один ЗЕЛЁНЫЙ. Текст падения верный и про предмет; дыра в ФИКСТУРЕ:
она шлёт ~6 МБ тела, сервер читает строку запроса, отвечает 401 и рвёт связь SetLinger(0) — и успеет ли
транспорт записать GotFirstResponseByte раньше, чем Do вернёт ошибку записи, решает гонка, а не
построение. ⇒ прежние RED этой записи были удачей.
Задача: перестроить фикстуру так, чтобы приход байта ответа был НЕИЗБЕЖЕН до обрыва, и предъявить 8 из 8 красных на посадке при 8 из 8 зелёных на дереве. Способ выбираешь сам.
5. Где этот пак мягкий — четыре места, назвал я, веер и глубину выбираешь ты
Мандат самопроверки — исполнением; субагенты разрешены явно. Адверсариальный проход по СВОЕЙ ГОТОВОЙ работе обязателен.
- ⛔ Пин, утверждающий только молчание, вакуумен ровно там, где сообщение ложно. «Ошибка не вышла наверх» — утверждение о молчании. Фикстура обязана быть такой, где новая причина ОБЯЗАНА прозвучать, и тест утверждает её ИМЯ.
- ⛔ Фикстура обязана сделать отказ резервации НЕИЗБЕЖНЫМ на попытке ≥1 и НЕВОЗМОЖНЫМ на попытке 0. Денежный пин, флейковый на мутанте, измеряет пустой сценарий: у нас уже был пин, дававший 2 красных из 8, потому что деньги были ВЕРОЯТНЫ, а не неизбежны. Гоняй свой не один раз.
- ⛔ Посадка обязана бить в тот же слой, что стережёт пин. За прошлый пак мутация трижды оказалась не про то: недостижимое условие в фикстуре · не собирающаяся посадка (НЕизмеренная — хуже выжившей) · код против гейта над данными.
- ⛔ Новая причина — факт ПРОВОДА, а не словаря. Тест, проверяющий только, что константа добавлена в
FlagReason, не доказывает, что читатель её увидит. Скажи, чем предъявлена дорога от флага до отчёта/экспорта.
⚠ И общее, стоившее трёх смен подряд: зелёная батарея плюс полный мутационный каталог сходимостью НЕ являются. В последних трёх паках направленный второй читатель находил 6, 7 и 9 дефектов при полной зелени.
⭐ Адверсариальная стойка — способ смотреть, не правило пака
- ⛔ Автор и ревьюер — разные роли, даже когда это один ты. Перечтение своей работы рубежом не считается: поднимай читателя, которому НАЗВАНО, где мягко.
- ⛔ Спрашивай у аномалии, о ЧЁМ она — о предмете или о твоём приборе.
- ⛔ Верный результат при неверном методе не краснеет нигде. «Сошлось» — не доказательство.
- ⛔ Утверждение о молчании вакуумно без фикстуры, где оно ОБЯЗАНО прозвучать.
- ⛔ Заимствованное число проверяется не на существование, а на ТУ ЛИ КЛЕТКУ: та же роль, та же модель, та же стадия, тот же режим?
- ⭐ Главный вопрос отчёта — не «что не получилось», а «что ты знаешь и не сказала».
⭐ Находки ВНЕ заказа — отдельный заказ владельца
Слово владельца 11.09: находить проблемы даже там, где мы не ждём. Задавай себе в каждой фазе вопрос, у которого нет заранее известного ответа: что здесь стоит дороже, работает хуже или ведёт себя страннее, чем должно бы, — и о чём никто не спрашивал? Ради чего он заведён: удорожание из-за падающих запросов на НАШИХ настройках никто не искал — просто кто-то посмотрел в леджер без гипотезы и увидел 25.4 % цены книги в выброшенных попытках, при зелёных тестах и молчащих гейтах.
Докладывай отдельной секцией: криты · мажоры · регрессии · баги · жёсткие точки улучшения — каждое
аргументированно, с носителем (file:line, число, команда) и с ценой в деньгах, тексте или доверии
читателя. ⚠ Секция обязана быть непустой ИЛИ нести строку «искал вот так, не нашёл» с перечислением мест:
«находок нет» и «не смотрел» в отчёте выглядят одинаково.
6. Предметные оси ревью
Выбери 1–3 и назови какие. Мой приор: деньги под гонкой · терминальное состояние прогона (что видит платформа и что видит человек) · обратная совместимость словаря причин.
7. Записка-план ДО работы
Перед первой правкой — записка: что меняешь, чем предъявишь, где ждёшь сопротивления. Комплектность против заказа сверяй механически.
8. Заявление = команда
Каждое число и каждая категорика отчёта — с командой, которой получены. Дифф ^func Test — исполнением,
не памятью. Приёмка пере-снимает.
9. Эхо-протокол старта
Первым действием — ≤10 строк СВОИМИ словами: что понял · что считаешь опасным · что считаешь неверным. Не пересказ: дословный пересказ подтверждает канал, но не понимание, и ошибку промта повторяет вместе с ним.
Адрес бери из /tmp/textmachine-channel — блок с role=оркестратор, — а не из этого промта: имя сессии
не переживает рестарт окружения. Перед отправкой сверься с ListAgents: файл переживает смерть сессии, а
ListAgents — нет.
10. Что НЕ удалось — обязательная секция отчёта
И вторая её половина: «где прибор слеп и я это знаю» — что невидимо · почему не чинил · чем закрывается. ⭐ Норма прошлой смены: «в коде названо, в отчёте нет — значит для следующей смены НЕ названо».
11. Канал вопросов и право отказаться
Конфликт промта с кодом или доками — пинг мне, не интерпретация. Право сказать «этого делать не надо» с аргументом у тебя есть и им пользовались: в двух случаях из трёх правы были сессии, а не я.
⛔ Тесты и гейты под зелень не подгонять. Правка, вызванная ЗАКАЗАННОЙ сменой поведения, — обслуживание, и протухший тест держать не нужно; но она ОБЪЯВЛЯЕТСЯ в отчёте: что изменилось, какой тест это описывал, куда уехала гарантия.
12. Прямой канал
Механизм — CLAUDE.md §«Связь между сессиями». Впиши свой блок в /tmp/textmachine-channel ПЕРВЫМ
действием. Нужной роли нет ⇒ канала нет, и это нормальный случай: НЕ опрашивай сессии подряд.
13. Критерий завершённости
У каждого пункта заказа — исход (сделано · не делаю с доводом · пинг) · круги СОШЛИСЬ (последний не дал
НОВЫХ находок; прежние закрыты таблицей «находка → что сделано → ЧЕМ ПРЕДЪЯВЛЕНО») · таблица мутаций
полная, выжившие названы, и КАЖДАЯ новая запись помечена battery (прошлый пак этого не сделал, и его
«21/21 RED» оказался разовым прогоном смены, а не гейтом проекта) · числа сняты ПОСЛЕ последней правки ·
всё живое в ДЕРЕВЕ, а не в письме · явное «работа завершена, править не планирую». Без последнего пак
считается идущим.