# Эмпирика прогонов Датированные факты: что поймал каждый этап конвейера, казусы, цифры. Дописывай после каждого прогона в конец файла — это и есть «выжимка опыта», ради которой скилл существует. Правку старых записей согласуй с пользователем: это долговечная эмпирика. Журнал накопительный, поэтому у него есть архив: записи с 2026-07-06 по структурный рефакторинг 2026-07-31 включительно лежат в [lessons-archive.md](lessons-archive.md) — они описывают заметно другую редакцию скилла. Живые хвосты тех записей перед переездом сведены в очередь на механизм (запись 2026-08-03). Когда файл разрастётся снова — подвинь границу и перенеси старое туда же: архив вне пути чтения прогона, поэтому его длина ничего не стоит, а дистилляция стоила бы потерянных историй. ## 2026-07-31: одёргивания за день прогонов (Opus 5-координатор, старая редакция) Фидбек пользователя после дня работы со скиллом; ценно тем, что это перечень мест, где координатора приходилось останавливать руками. 1. **Повторное ревью отревьюенной постановки.** Координатор ревьюит готовый тикет, уже прошедший ревью на этапе постановки. Правило «одно ревью на версию артефакта» в этапе 2 ЕСТЬ (записано 2026-07-21) — и не держит. Класс отказа тот же, что с вкусовой линзой (запись 2026-07-31, в архиве): правило в прозе не исполняется, нужен механизм — например, перед этапом 2 координатор обязан назвать, какая версия тикета когда ревьюилась, и пропустить этап, если версия не менялась. 2. **Переоценка сложности.** Полный цикл ревью там, где хватило бы саморевью. Шкала риска этапа 4 есть — и тоже не держит: дефолт скилла «полный состав минус пропуски» (opt-out), координатор склонен к максимальной церемонии. Кандидат на следующий заход: перевернуть дефолт — минимальный хребет (постановка → исполнитель → саморевью → приёмка) + явные триггеры эскалации (opt-in); добавить слой дешевле, чем отменить запущенный. 3. **Код Кодекса нельзя показывать ученикам.** Формально задачу решает хорошо, но «не хочу их учить так писать» — это не дефект кода, это дефект назначения исполнителя. Боевое подтверждение оси вкуса, принятой этим же днём: в учебном репозитории почти всё читает человек → почти вся реализация уходит `craftsman`'у, Codex — на обвязку и инфраструктуру. Проверить следующим прогоном, снимает ли новый разрез эту боль. 4. **Скилл зовут ради механики субагентов, не ради конвейера.** Регулярный сценарий: дать агенту знание «субагенты существуют, вот как их звать» для специальной задачи — а вызов тянет весь конвейер. Это отдельная ветка использования: дисциплина делегирования (Роли, определения, файлы-вместо-пересказов) полезна вне цикла разработки. Кандидат: выделить её в лёгкий скилл или отдельную точку входа, чтобы «субагентная грамотность» не стоила 300 строк процесса. Пункты 1–2 и 4 — открытый вопрос следующего структурного захода (сегодняшний рефакторинг закрыт коммитом 3e0498e, не расширять задним числом). ## 2026-08-01: триаж судит находку, но не лечение (clickstream v2, тикет #36) Конфигурация редкая: оркестратор и есть исполнитель — плейбук позвали поверх готовой работы `/implement`, третьей линией (Кодекс, high) к двум уже прошедшим Клод-линиям. Пересылать индекс некому, триаж вёлся в голове; статусы по ID появились файлом только ради перепроверки, задним числом. - **Все три находки верны, одно лечение — перебор.** REV-1 «имена не с чем сверить» я закрыл записью 47 имён второй копией — то есть прибил гвоздями решение чужого слоя (имена атрибутов складывает модель DDS, спека задала только вид имени). Поймал владелец вопросом «ты прибил гвоздями?», не процесс. Триаж в скилле судит находку (FIXED / REJECTED / …), а лечение проезжает без суда — тем более что колонка «как проверить» у Кодекса фактически лечение и предписывает. - **`NEEDS_DECISION` был доступен и не сработал.** Починка замораживала решение будущего тикета — ровно его случай. Не опознал, потому что правка выглядела дешёвой: 47 механических строк. Урок-обобщение: дешевизна починки ничего не говорит о том, чьё это решение. - **Перепроверка тем же ревьюером перебор не ловит структурно**: вернула `ALL_CLOSED`, подтверждая реализацию собственного предписания. - **Промах в промпте ревью**: перечислены источники истины, но не «какие решения ещё открыты и кем владеются» — ревьюер физически не мог знать, что имена DDS не наши. Кандидат: обязательный блок открытых решений. - Цифры: ревью 124 команды, 3 находки (2 MAJOR, 1 MINOR); перепроверка на medium — 46 команд. Одна находка фактическая (комментарий рекламировал торговые события, от которых спека отказалась) — её обе Клод-линии пропустили: подтверждение ценности другой родословной. ## 2026-08-02: перепроверка толкает лечение в обе стороны (clickstream v2, тикет #38) Конфигурация та же, что 08-01: оркестратор он же исполнитель, Кодекс (high) третьей линией к двум прошедшим Клод-линиям. Снова три находки, все верны; снова другая родословная дала класс, мимо которого прошли обе Клод-линии — честность тестов: сторож сравнивал день −N с днём N, а сталкиваются −N и N−1. - **Перепроверка тем же ревьюером не судит соразмерность лечения ни в одну сторону.** 08-01 она вернула `ALL_CLOSED`, подтвердив исполнение собственного предписания; здесь на ту же починку — `NOT_CLOSED` с требованием недостижимого (полная неприкосновенность запомненной когорты: в numpy владелец памяти размораживается всегда, а вид всегда показывает `.base`). Одна дыра, две стороны. Приём: на `NOT_CLOSED` проверять не только факт, но и существует ли закрывающее состояние, и мерить цену альтернативы — здесь 16 МиБ копий на день вместо 2 мс, то есть размен реального свойства на защиту от умысла. - **Долг 08-01 не закрыт: статус вешается на находку, не на лечение.** Здесь лечение судилось только потому, что владелец потребовал этого в постановке («Кодекс коварен, польза бывает очевидна на первый взгляд»). Механизма по-прежнему нет. - **Новый класс: сломан не код, а измерительный прибор.** Цикл мутаций «правка → прогон → откат» внутри секунды оставлял устаревший `.pyc` (свежесть — по времени правки и размеру), тесты шли по байт-коду мутанта и падали на восстановленном дереве. Чуть не «починил» работающее. Линии ревью смотрят на код и такого не ловят; конвейер молча допускает, что проверялка оркестратора исправна. Приём: мутации гонять с `PYTHONDONTWRITEBYTECODE=1`, первым и последним прогоном — чистое дерево. - **Польза линии пришла как «изменил, что я проверяю»**: находка развернула батарею мутантов на дерево зёрен, которое я считал очевидным, — там нашлись ещё два слепых сторожа. Слить ветвь дней с ветвью состава можно было, не уронив ни одного из 297 тестов. - Цифры: ревью 68 команд, 3 находки (1 MAJOR завышен — сценарий требует сознательно снять флаг у массива, 2 MINOR); перепроверка на medium — 12 команд; батарея 17 мутантов, выживших нет. ## 2026-08-02: долг «суда над лечением» закрыт шапками (clickstream v2, тикет #39) Штатная конфигурация: реализация — Опус-мастеровой, линия кода — Кодекс (high) свежим тредом, линия задачи и вкуса — свежий Опус. Долг двух прошлых прогонов закрыт руками: в шапку триажа и в шапку перепроверки дописаны абзацы про соразмерность лечения (заготовки прогона; перенесены в шапки 2026-08-03). - **Ручка сработала трижды за один прогон.** Перепроверка вкусовой линии сама оценила правку спеки на перебор (вышла за границу промпта — принята с доводом: четыре фразы без поведения, чинят противоречие, внесённое этим же изменением), приняла закрытие маршрутом, отличным от подсказанного («запрет был не той половиной, которую надо чинить»), и обосновала соразмерность нового модуля. Без ручки всё три проехали бы молча, как в #36. - **10 FIXED, 0 REJECTED — повод посмотреть на лечения, а не приговор.** Перебора не нашлось, но узнал я это проверкой, а не по отсутствию отказов. - **Пересечение линий — ноль из десяти, и каждая принесла свою дыру в честности тестов.** CODE-1: слепок детерминизма не включал ни порядок колонок, ни публичные швы для соседнего тикета — перестановка колонок через вызов проходила все три сторожа. TASK-4: сторож правил нарезки ловил склейку двух визитов, но не разрез одного. Разные тесты, разные механизмы. - **Тонкий лог перепроверки — повод проверить MAJOR самому.** 8 команд против 58 в самом ревью; закрытие единственного MAJOR перепроверил своим зондом (перестановка колонок, правка каждого шва, стабильность того же дня) — закрыт честно. Цена приёма — один скрипт оркестратора. - **Два отказа вызова Кодекса, оба от чтения правил без разбора.** `< /dev/null` по правилу «фоновому запуску закрывай stdin» убивает промпт, который сам идёт через stdin (`No prompt provided via stdin`), — правило не про этот случай. И `codex exec resume` (0.145.0) не принимает `-s`/`-C`: среда треда задана при создании и на продолжении не переуказывается; остальные ключи (`-m`, `-c`, `-o`, `--json`) те же, что у `exec`. Уточнено 2026-08-03: хвост «песочница только через `-c sandbox_mode=…`» был неверен — ключ разбирается, но среду продолжения не меняет. Оба отказа закрыты по месту: `codex-exec.md` (рецепт resume и правило stdin), `SKILL.md` этап 6 (правило `< /dev/null` сужено условием «нечего читать со входа»). - Цифры: два ревью — 58 и 36 команд/инструментов, 10 находок (1 MAJOR, 8 MINOR, 1 NIT); триаж — 10 FIXED; перепроверки на medium — 8 и 12; тесты 297 → 353. ## 2026-08-02: шапки соразмерности сработали в третий раз (clickstream v2, тикет #40) Конфигурация редкая по исполнителю: тикет залезал на территорию трёх соседних (план состава #38, воронка и каталог #39), и вкусовую реализацию вёл не `craftsman`, а `deep-reasoner` — решение пользователя, обоснование: не письмо по готовой форме, а калибровка «померил — подкрутил — померил» под вилки мира. Оправдалось: 41 минута, 26 новых тестов, числа мира легли в вилки с первого захода. Линия кода — Кодекс (high) свежим тредом, линия задачи и вкуса — свежий Опус. - **Пересечение линий — одна находка из девяти, и обе линии описали её по-разному.** Полуночная потеря покупки при выжившей странице подтверждения: Кодекс сконструировал сценарий и дал MAJOR, Опус померил 14 канонических дней, нашёл ноль случаев и записал в необязательные соображения. Не спор, а два свидетельства об одном латентном дефекте (окно ~7 с на заказ). Приём: сводя вердикты, ищи не совпадение формулировок, а совпадение явления — разная оценка достижимости у линий нормальна и полезна. - **Шапка соразмерности лечения окупилась на MAJOR'е.** Исполнитель отклонил маршрут ревьюера («проверь симптом там, где он виден») и починил слоем выше — граница суток даёт подтверждению место под торговый хвост. Довод сильный: починка внутри `commerce` двигала бы просмотры страниц при правке торгового подпотока, то есть ломала бы ровно то свойство, о котором вторая находка того же ревью. Без шапки предписание проехало бы молча, как в #36. - **9 FIXED / 0 REJECTED — и одно ослабление порога всё же было.** TASK-3: группа стала строже (пары исключены), измеренный лифт упал ×4,7 → ×3,0, и порог теста опущен `> 3` → `> 2`. Обосновано, но это ровно тот ход, от которого предостерегает шапка, — судить его отдал перепроверке той линии, что находку и подняла. Вернулась CLOSED с воспроизведёнными числами. - **Тонкий лог перепроверки Кодекса (10 команд) — снова повод проверить MAJOR самому.** Свой зонд оркестратора: 14 дней × два режима, включая стресс с часовым торговым хвостом (окно, в котором дефект жил) — ноль подтверждений без покупки и ноль покупок без подтверждения. Приём из #39 подтверждён. - **Приёмка глазами нашла то, чего не даёт ни один вердикт: урок виден в данных.** Распечатал один визит целиком и померил разрыв: у 157 покупок из 272 сумма по разобранным массивам не равна `purchaseRevenue` (2680 против 2679,8). Ради этого копейки в каталог и заводились — без своего прогона осталось бы верить отчёту. - Цифры: реализация 41 мин / 328k токенов, саморевью 8/8; ревью — Клод 33 инструмента, Кодекс 120 команд; 9 находок (2 MAJOR, 5 MINOR, 2 NIT), пересечение 1; триаж 9 FIXED за 13 мин; перепроверки 13 и 10 команд, обе ALL_CLOSED + 1 новый NIT (повтор фразы в спеке, внесённый починкой TASK-2) — поправил сам по месту. Тесты 353 → 383. - **Долг скилла остаётся тот же**: абзацы про соразмерность лечения третий прогон подряд пишутся руками. Закрыт 2026-08-03. ## 2026-08-02: сломанный прибор доезжает до коммита (clickstream v2, тикет #50) Продолжение #40 после грилинга: реализация — `deep-reasoner` (калибровка чисел мира), линия кода — Кодекс (high) свежим тредом, линия задачи и вкуса — свежий Опус. Ревью постановки — одна линия (Кодекс), вторая пропущена: решения уже прогриллены и лежат в спеке. - **Ошибка измерения всплыла трижды на трёх уровнях, и ни разу её не поймал тот, кто мерил.** (1) Оркестратор мерил на зерне 0, а весь мир и все тесты живут на `CANONICAL_SEED` — поймало ревью постановки; (2) в знаменателе «просмотры карточек» сидели строки событий корзины, потому что событие садится на ту же страницу, — поймал исполнитель; (3) маска «строка с массивом товаров» захватывала и строку покупки — поймал сам оркестратор, сверив арифметику отчёта. Два из трёх уже уехали в коммит спеки. Класс дефекта не новый (#38 — устаревший `.pyc`), но новое здесь то, что прибор ломается на **чтении** данных, а не на прогоне, и потому переживает и тесты, и ревью кода. Приём: числа, попадающие в постановку и спеку, сверять арифметикой независимо от источника — сумма частей, тождества между колонками; и называть зерно явно везде, где написано «канонический день». - **Наблюдение владельца по итогам дня: Кодекс дрейфует к букве.** Прогон его уточняет, а не подтверждает целиком. На **постановке** Кодекс работал ровно по смыслу — половина из девяти находок это охота на формальность («критерий закрывается одним визитом», «требование живёт в прозе, а не в чекбоксе»). На **коде** он вернул 1 MINOR за 120 команд и прошёл мимо главного дефекта прогона — дефекта цели, видного только тому, кто держит в голове, зачем тикет заведён. Часть промаха назначена линзой оркестратора («не дублируй вкусовую линию»), но остаётся устойчивый осадок из #36/#38/ #40: **лечения** Кодекса буквальны даже внутри его линзы. Кандидат в механизм (не решение): требовать от линии Кодекса перед индексом один абзац — «что сделает эту правку провальной, даже если все критерии зелёные». - **Шапка соразмерности сработала дважды за прогон.** Исполнитель отверг предложенный ревьюером ряд вероятностей, перемерив его (давал 1,84 при требуемых 2), и закрыл находку другим маршрутом; перепроверка поймала необязательный сдвиг порога (0,05 → 0,03 при измеренных 7,25% — старый пол проходил). Второе — новый факт: **порог, сдвинутый и честно объявленный, всё равно бывает лишним**; объявление снимает скрытность, но не заменяет проверку необходимости. - **Ревьюер признал своё предложение неверным на перепроверке** — раньше такого не встречалось. Перепроверка, которой явно поручено судить лечение, судит и собственное предписание. - **Приёмка глазами снова дала то, чего не даёт ни один вердикт**: один распечатанный визит показал новый сюжет целиком (шесть карточек, две в корзину, корзина не открыта) и заодно, что кладут не только магниты, — то есть главная правка видна на одном случайном примере. - Казус: `make` в промпте звался из `generator/`, а Makefile лежит в корне — три «красных» прогона на пустом месте, и ревью постановки этого не поймало (команды проверки оно не запускало). - Цифры: ревью постановки 32 команды / 9 находок, все приняты; реализация ~31 мин, саморевью 3/3; слепые ревью — Опус 28 инструментов / 7 находок, Кодекс 120 команд / 1, пересечение **ноль**; триаж 8 FIXED + второй круг на 1 новую находку, 0 отклонённых; перепроверки 15 и 18; тесты 383 → 394. - **Долг четвёртый прогон подряд тот же**: шапки соразмерности так и не перенесены. Закрыт 2026-08-03. ## 2026-08-03: долг соразмерности закрыт, и найдена его настоящая причина Сессия без прогона: разбор `lessons.md` по `/writing-great-skills` и правка шапок. Долг, висевший с #39, закрыт — правки лежат в `prompts/triage-header.md` и `prompts/recheck-header.md`, содержание там, здесь не дублирую. - **Причина не в размере починки, а в весе слова** (диагноз пользователя). Пока код писал Кодекс, а ревьюил Опус, послушный исполнитель был прав: ревьюер сильнее как архитектор. После разворота ролей — вкусовая реализация Опусом, ревью Кодексом — послушание стало вредным: Кодекс очень сильный исполнитель, но слабее как мыслитель-архитектор, настойчив, склонен к формализации без учёта высокоуровневой цели и продавливает Опуса на свои решения. Перекос усиливает разница ступеней: Опус на medium против Сола на high уступает ещё и по «званию». - **Цифра под диагнозом**: #39, #40, #50 — около 28 находок, ноль отклонений. - **Два кандидата сняты сверкой с эмпирикой, а не по вкусу.** Требование объявлять ослабление порога отдельной строкой — против него сам урок #50 («объявление не заменяет проверку необходимости»), а оба случая (#40, #50) поймала перепроверка. Пункт «оценивай довод исполнителя, а не факт несогласия» — дубль строки, уже стоявшей в шапке. - **Правило об арбитре в споре не писалось намеренно**: спора ни разу не было (ноль отклонений), правило под несуществующую ситуацию есть перерегулирование. Ждём первого отклонения — новые шапки как раз должны его породить. - **Разбор самого файла**: 783 строки, 22 записи; собственное правило «поглощён урок — сожми до строки-факта» сработало один раз (07-12) и с тех пор нет — записи после него по 30–80 строк, часть держит вторую копию действующих правил SKILL.md. Дистилляция архива вынесена отдельным заходом. **Очередь на механизм** (сведена сюда, чтобы не искать по всему файлу): блок открытых решений в промпте ревью — «какие решения ещё открыты и кем владеются» (#36); абзац от линии Кодекса «что сделает эту правку провальной, даже если все критерии зелёные» (#50); приёмы против сломанного прибора оркестратора (#38 — `PYTHONDONTWRITEBYTECODE=1` и чистое дерево крайними прогонами; #50 — арифметика чисел, попадающих в спеку, и явное зерно; #39/#40 — тонкий лог перепроверки как повод проверить MAJOR своим зондом; #40/#50 — один пример целиком на приёмке); мелочи по месту — сведение вердиктов по совпадению явления, а не формулировки (этап 5), ревью постановки не запускает команды тикета (этап 2), оговорка про `< /dev/null` рядом с приёмом в `codex-exec.md`; старьё — ранжирование правил задачи (07-07), эхо файла задачи (07-13), A/B на gpt-5.6-terra (07-13), пп. 1–2 и 4 одёргиваний (07-31). ## 2026-08-04: находки холодного ревью долечены; запрет против значения Сессия без прогона, продолжение 08-03: триаж находок холодного ревью самого скилла. Что именно поправлено — в коммитах от `c18472e`, здесь не дублирую. - **Правило, нарушаемое рассуждением, лечится значением, а не ещё одним запретом.** «Не режь ревьюеру read-only» стояло в двух местах — и было нарушено при сборке команды для этого же холодного ревью: не по незнанию, а доводом «ревью документа рук не требует». Промпт при этом сам обещал ревьюеру опыты во временных файлах, которые песочница запрещала, — тред пришлось убить и перезапустить. Вылечено тем, что песочница названа значением с причиной при нём, а ветке ревьюера дан целый рецепт: не осталось повода собирать команду руками. - **Случай третий той же формы** (два прежних в архиве: 07-22 канал обёртки, 07-30 `danger-full-access` «на всякий случай» из-за оговорки «боем не обкатано»). Отказ скилла — не отсутствующее правило, а правило, оставляющее рассуждению право на исключение; оговорка в рецепте читается как приглашение к самодеятельности. - **Скретчпад поднимается из транскрипта сессии.** Ребут стёр каталог; шесть документов восстановлены fast-worker'ом из JSONL сессии (`~/.claude/projects/<проект>/.jsonl`): вызовы Write отдают тело дословно, файлы чужих процессов — из эха Read с обрезкой номеров строк. Не поднимаются промпты, ушедшие в `cat ... |` на stdin: их тело в транскрипт не попадало. Цена — 48k токенов субагента, три минуты. - **Вывод под этим**: пережить сессию должно то, что лежит вне скретчпада. Индексы находок целиком не переносим — в handoff идут открытые, с номером и доводом линии; закрытые читаются по коммитам. - **Диагноз пользователя: краткость исполнителя ломает решение.** Метку NEEDS_DECISION ставит тот, кто единственный держит код в голове, а наверх уходит голый вопрос — координатор кода не читал по устройству ролей, владелец тем более. Дословно: «Опус пишет так, как будто я очень хорошо разбираюсь в коде и проблеме, а так бывает далеко не всегда». Отсюда требование вариантов, их цены и рекомендации — и к исполнителю, и к координатору, когда он несёт развилку владельцу. ## 2026-08-06: вывод Кодекса теряет харнесс, а не версия Запись переписана в тот же вечер: первая редакция валила отказ на версию codex-cli 0.146.0 и была неверна. Развели две проверки — холодная A/B (изолированная установка 0.146.0 рядом с глобальной 0.146.1, обе штатны) и контрольные прогоны изнутри харнесса, где отказ живёт и на 0.146.1. - **Версия ни при чём.** Чистые 0.146.0 и 0.146.1 на этой же машине пишут в перенаправленный файл штатно: `codex --version > f` — 18 байт, `--json` — семь строк JSONL с `thread.started` и `command_execution`. Списать отказ на версию — первый соблазн: он объясняет всё и не требует ничего. Цена проверки — десять минут на установку в отдельный префикс, и она стоит того, чтобы гипотеза не уехала в журнал утверждением. - **Ось — файл против канала.** Изнутри харнесса T3 Code (SDK-хост) на 0.146.1: `codex --version > f` — ноль байт и код 0, `codex --version | cat > g` — 18 байт. То же на полном вызове: `exec --json … > log` — пусто, он же через `2>&1 | cat > log` — семь строк, thread_id в первой, `command_execution` дважды. Отчёт `-o` пишется в обоих случаях: файлы, которые Кодекс открывает сам, целы — пропадает унаследованный дескриптор, когда за ним файл. Stderr так же: `Error loading config.toml…` виден только через канал. Отключение песочницы Bash ничего не меняет. - **Тот же разрез объясняет и вход.** `exec - < prompt.md` изнутри даёт `No prompt provided via stdin` и код 1, `cat prompt.md |` работает; вне харнесса работают оба. Одна причина на обе находки первой редакции — и обе снимаются каналом. - **Не всякий харнесс — этот харнесс.** В Claude Code CLI 2.1.223 на той же машине и той же 0.146.1 всё штатно: файл на выходе — 18 байт, лог — семь строк, `- < prompt.md` читается. Ярлыку «я в агенте» не верь, спроси среду сама — самотест стоит пять секунд и живёт предполётом в [codex-exec.md](codex-exec.md). - **Лечение живёт в рецептах, не здесь.** Форма сбора — каждый поток своим каналом в свой файл — стоит там же, в предполёте, и включается по результату самотеста; сами рецепты не правились. Три вещи, которые стоили отдельной проверки. `2>&1 | cat` короче и подкладывает ошибку разбора: строка stderr в JSONL ломает `jq` и может встать первой вместо `thread.started`. Канал глотает код возврата (`false | cat` даёт ноль) — отсюда `set -o pipefail` в форме. Псевдотерминал из первой редакции не нужен: `script` давал тот же JSONL ценой `\r` и непереносимости. - **Механизм не вскрыт.** Известно поведение, не причина: файл на входе и выходе дочернего процесса пуст, канал цел, песочница ни при чём. Пишу это свойством среды и не выдаю за объяснение. - **Цена неверной атрибуции — коммит в репозиторий скилла.** Правило «пока причина не снята запуском с одним изменением, она гипотеза» у меня было — и не спасло: внутри серии я честно менял по одному параметру, но вся серия целиком стояла в одной среде, и согласованность её прогонов читалась подтверждением. Отсюда добавка к правилу: среда — тоже параметр, и первый кандидат на подозрение, когда наблюдение расходится с документацией инструмента. Сняла ошибку чужая проверка, не моя. - **Уцелевшая ловушка**: запуск из недоверенного каталога (пробовал из `/tmp`) даёт `Not inside a trusted directory and --skip-git-repo-check was not specified.` Снаружи это видно в stderr и коде 1; изнутри харнесса сливается со всеми прочими отказами в пустоту и код 1. - Цифры: два захода контрольных прогонов, промпт односложный («выполни `pwd`»), `model_reasoning_effort="low"`; отчёт `-o` — 46 байт в каждом, лог через канал — семь строк. ## 2026-08-27: три линии по нулям на ошибке формы (clickstream v2, #158) Прогон DQ-контура: реализация Codex, линия уместности Fable, две слепые резервные линии. Все три дали ноль находок; ошибку увидел пользователь одним вопросом «почему DQ на Python, а не SQL». - **Находка жила выше диффа.** Агрегация ключевого зерна шла в Python: 57 567 ключей сессий ехали из ClickHouse в процесс Airflow ради суммирования. Код опрятный, ни один из двенадцати запахов не задет — линза, читающая код, пройти мимо была обязана. - **Промах не был бесплатным.** Та же граница была причиной саги с памятью: OOM планировщика в 640 МиБ, восемь ресурсных ручек в трех дагах. Ревью объяснило сагу теснотой коробки — гипотезой из постановки — и не спросило, почему задача, пишущая три десятка строк сводки, ест сотни мегабайт. - **Механизм промаха — порядок чтения.** Ревью от диффа принимает раскладку исполнителя как оглавление; внутри чужой рамки видно кривое имя, но не то, что раскладка не та. Фронтирный исполнитель пишет чистый код вокруг неверных решений: ошибки живут в форме, не в отделке — то же наблюдение, что в прогоне #18. - **Лечение — механизм, не правило в прозе** (класс отказа записан 2026-07-31): в `line-taste.md` добавлен shape-проход шагами до чтения диффа — набросок ожидаемой формы из одной постановки, список недиктованных решений, вердикт каждому. Артефакты предъявляются как checks run даже при нуле находок — слот уже был в `review-boilerplate.md`. Запрет «не читай дифф первым» не произносится: его исполняет порядок шагов. - Проверить следующим прогоном: ловит ли shape-проход ошибку класса #158 и не сжигает ли ревьюер бюджет до диффа (граница «a few lines suffice»). ## 2026-09-09: аудит плюс реализация одним усилием (t2-ml-forecast, #22 + #18) Прогон: разведка Explore, аудит Codex high, гриллинг с владельцем в чате, ревью постановки deep-reasoner, реализация Codex high, саморевью, две слепые линии (craftsman и Codex), триаж, перепроверка, коммит, трекер. - **Аудит перевернул постановку.** Тикет просил «проверить, что умеет механизм»; прогон показал, что чинить его дороже, чем заменить (ошибка на схеме заказчика, нет окна действия). Объединение с тикетом-решением в одну сессию сэкономило цикл передачи контекста; владелец такое объединение приветствует, формализм границ ему не нужен. - **Ревью постановки поймало блокер, который тесты не поймали бы:** инвариант `Slice.coherent` отвергал любой результат с условиями, и без него приёмка была недостижима. Ни разведка, ни постановка этого не знали. Этап 2 окупился одним этим. - **Sol без вкуса, подтверждено.** Код верный и полный, форма первая попавшаяся: ручная валидация на 100 строк рядом с pydantic, хвост из семи аргументов, `assert` как страж. Разрез «вкусовая часть сначала» был пропущен: постановка предлагала «dataclass или pydantic», и исполнитель выбрал буквальный путь. Контракты и разбор входа — Opus. - **Накрутки Codex, два случая за прогон.** По находке ревью он завёл четыре теста, которые читают markdown и проверяют формулировки документов; по находке про формулы в Excel запретил символы ещё и в поле, которое не выгружается (перепроверка вернула OVERREACH). Лечение строкой в шапке триажа: «тесты только на поведение, не на текст документов; чини ровно то место, что названо». - **Перепроверка тем же ревьюером принесла новую находку**, не только подтверждение: OVERREACH и указание, что дыра сидит в экспорте, а не в условиях. Заведён отдельный тикет, в скоуп не тянули. - **Два писателя в одном дереве без конфликта.** Владелец в соседней сессии правил другие файлы; коммитил только файлы из отчёта исполнителя по явному списку. Ревьюерам список «шум дерева» подшит в параметры отдельным блоком, иначе они ревьюят чужое. - **T3 Code: bwrap `RTM_NEWADDR` в песочнице Codex не фатален.** Четыре ошибки на `apply_patch`, обошёл сам через heredoc; 58 команд прошли. - **`AGENTS.md`-правило «перечитывай issue после сжатия»** заставило саморевью Codex перечитать GitLab и запустить сверку витрин через `bpc_f2_export` (минуты). Полезно, но долго; сторож на застой необходим. - **Расход контекста оркестратора:** два полных чтения (разведка 419 строк, вердикт ревью постановки) дали больше всего. Разведку просить индексом до 80 строк с путями; вердикты читать только строками находок через grep. ## 2026-09-11: накладные расходы конвейера против «сделать самому» (t2-ml-forecast, #36) Тикет #36: условие с инерцией, семь файлов, все развилки закрыты ответами бизнеса и оркестратором до старта. Конвейер развёрнут по плейбуку: файл-задача, craftsman исполнителем, Astra ревьюером. - **Замер контекста оркестратора (тысячи токенов, оценка).** Конвейер: чтение плейбука и справочников 22, сбор фактуры 8, файл-задача и промпты 5, приёмка ~10, итого ~45. Своими руками: чтение кода 15, правки и тесты 10, приёмка 5, итого ~30. Разница целиком в фиксированной плате за плейбук: вторая задача в той же сессии стоит конвейером ~20. - **Слова владельца.** У Astra как оркестратора накладные расходы на постановку, оркестрацию и приёмку во многих случаях превышают экономию от делегирования; её оркестрация тяжелее, чем у Fable, хотя и мощнее. Экономика субагентов полезна для ревью, где нужен чистый контекст, и редко для разработки. - **Следствие для вводных скилла (переписать позже):** одиночная задача с закрытыми развилками до десятка файлов делается оркестратором самостоятельно, конвейер сводится к слепому ревью. Исполнитель-субагент оправдан при нескольких задачах в сессии или при открытых решениях, когда контекст оркестратора нужен для них, а не для кода. - **Лишняя плата этого прогона:** часть фактуры ушла на ловушки Codex (snap `uv`, зависание `TestClient` в песочнице), хотя исполнителем в итоге выбран Claude. Исполнителя выбирать до чтения справочника по механике вызова.