diff --git a/agents/.agents/skills/claude-subagent-playbook/references/lessons.md b/agents/.agents/skills/claude-subagent-playbook/references/lessons.md index d093f5f..769b43c 100644 --- a/agents/.agents/skills/claude-subagent-playbook/references/lessons.md +++ b/agents/.agents/skills/claude-subagent-playbook/references/lessons.md @@ -334,51 +334,51 @@ Отсюда требование вариантов, их цены и рекомендации — и к исполнителю, и к координатору, когда он несёт развилку владельцу. -## 2026-08-06: Кодекс 0.146.0 молчит мимо терминала — три механизма слепнут +## 2026-08-06: вывод Кодекса теряет харнесс, а не версия -Сессия без прогона. Хвост от тикета #54 (clickstream v2): там вызовы Кодекса -трижды падали вхолостую, причину я тогда назвал неверно. Здесь она снята -четырьмя контрольными прогонами — codex-cli **0.146.0**, Linux, запуск из -Bash оркестратора, то есть stdout всегда перенаправлен. +Запись переписана в тот же вечер: первая редакция валила отказ на версию +codex-cli 0.146.0 и была неверна. Развели две проверки — холодная A/B +(изолированная установка 0.146.0 рядом с глобальной 0.146.1, обе штатны) и +контрольные прогоны изнутри харнесса, где отказ живёт и на 0.146.1. -- **Нет терминала — нет stdout.** 0.146.0 не пишет в перенаправленный stdout - ничего: `codex --version` отдаёт пустой файл и код 0, `--json` — пустой - лог. От `-o` это не зависит: без него лог так же пуст, а отчёт `-o` - пишется нормально. Сообщения об ошибках уходят туда же, поэтому **любой - отказ запуска выглядит одинаково** — пустота и код 1. Так же молча падает - и запуск из недоверенного каталога (пробовал из `/tmp`: под терминалом - видно `Not inside a trusted directory…`). -- **Отсюда слепнут три механизма рецепта, и все три — молча.** thread_id - «из первой строки stdout-JSONL» взять неоткуда, а на нём висят саморевью - этапа 3 и вся ветка триажа через `resume`. Сторож видит файл нулевого - размера: первый тик `prev=0`, второй — `STALLED`, то есть ложная тревога на - десятой минуте любого долгого прогона. Проверка отписки - (`grep -c '"command_execution"'`) даёт ноль на честной работе — и рецепт - велит перезапускать дорогое ревью. -- **Промпт читается только из канала.** `codex exec … - < prompt.md` отвечает - `No prompt provided via stdin.` и выходит с кодом 1; `cat prompt.md |` тем - же вызовом работает. Обычный файл на входе для 0.146.0 — это «промпта нет». - Ловушка в диагностике: сообщение то же самое, что при `< /dev/null` - (запись 2026-08-02, #39), — и уводит искать закрытый stdin вместо формы - входа. Рецепты в `codex-exec.md` собраны через `cat`, поэтому копирующий - агент мимо этого проходит; я собирал команду руками и попал. -- **Диагноз без контрольного прогона промахивается по причине.** Первую - находку я записал как «пусто, когда задан `-o`»: в падавших запусках - менялось сразу несколько вещей. Развела их серия из четырёх прогонов, - различающихся ровно одним параметром. Урок общий: пока причина не снята - таким запуском, она гипотеза. -- **Обход, оба проверены.** Псевдотерминал: `script -qec '<та же команда>' - /dev/null > log.jsonl` даёт полный JSONL — `thread.started` с id, - `command_execution` — и отчёт `-o` на месте; строки заканчиваются на `\r`, - перед `jq` нужен `tr -d '\r'`; только Linux, у macOS другой синтаксис, в - Git Bash `script` нет. Переносимо и без обвязки — журнал самого Кодекса: - `~/.codex/sessions/ГГГГ/ММ/ДД/rollout-*-.jsonl`. Имя несёт - thread_id (сверил с `thread.started` — совпал), файл растёт по ходу и - содержит записи выполненных команд, то есть закрывает и признак жизни для - сторожа, и доказательство работы вместо отписки. -- **Кандидат в механизм**: `codex-exec.md` держит правило «промпт через - stdin» и приём проверки отписки в редакции, которая на 0.146.0 не - работает. Правка не написана — решение за владельцем. -- Цифры: четыре прогона по односложному промпту («выполни `pwd`»), - `model_reasoning_effort="low"`; отчёт `-o` — 46 байт, JSONL под - псевдотерминалом — 7 строк, журнал прогона — 19 строк. +- **Версия ни при чём.** Чистые 0.146.0 и 0.146.1 на этой же машине пишут в + перенаправленный файл штатно: `codex --version > f` — 18 байт, `--json` — + семь строк JSONL с `thread.started` и `command_execution`. Списать отказ + на версию — первый соблазн: он объясняет всё и не требует ничего. Цена + проверки — десять минут на установку в отдельный префикс, и она стоит + того, чтобы гипотеза не уехала в журнал утверждением. +- **Ось — файл против канала.** Изнутри харнесса (Bash Клода, T3 Code) на + 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 |` работает; вне + харнесса работают оба. Одна причина на обе находки первой редакции — и обе + снимаются каналом. +- **Правило для этой среды**: и промпт, и лог гнать каналом — + `… 2>&1 | cat > "$D/…jsonl"`. Так живут все три механизма рецептов: + thread_id из первой строки, сторож по росту лога, проверка отписки через + `command_execution`. Псевдотерминал из первой редакции не нужен: `script` + давал тот же JSONL ценой `\r` и непереносимости. Сами рецепты + `codex-exec.md` вне харнесса верны и не правились. +- **Механизм не вскрыт.** Известно поведение, не причина: файл на входе и + выходе дочернего процесса пуст, канал цел, песочница ни при чём. Пишу это + свойством среды и не выдаю за объяснение. +- **Цена неверной атрибуции — коммит в репозиторий скилла.** Правило «пока + причина не снята запуском с одним изменением, она гипотеза» у меня было — + и не спасло: внутри серии я честно менял по одному параметру, но вся серия + целиком стояла в одной среде, и согласованность её прогонов читалась + подтверждением. Отсюда добавка к правилу: среда — тоже параметр, и первый + кандидат на подозрение, когда наблюдение расходится с документацией + инструмента. Сняла ошибку чужая проверка, не моя. +- **Уцелевшая ловушка**: запуск из недоверенного каталога (пробовал из + `/tmp`) даёт `Not inside a trusted directory and --skip-git-repo-check was + not specified.` Снаружи это видно в stderr и коде 1; изнутри харнесса + сливается со всеми прочими отказами в пустоту и код 1. +- Цифры: два захода контрольных прогонов, промпт односложный («выполни + `pwd`»), `model_reasoning_effort="low"`; отчёт `-o` — 46 байт в каждом, + лог через канал — семь строк.