docs(skills): урок 08-06 переписан — вывод теряет харнесс, не версия
- Зачем:
- первая редакция объявляла отказ свойством codex-cli 0.146.0. Чистые
0.146.0 и 0.146.1 на этой же машине пишут в перенаправленный файл
штатно, значит запись вела следующего читателя чинить рецепты от
несуществующей поломки.
- Что:
- запись 2026-08-06 переписана: ось не «терминал против всего», а файл
против канала, и живёт она в харнессе, а не в версии; одна причина на
обе прежние находки, обход — канал вместо псевдотерминала.
- методическая часть усилена: среда — тоже параметр серии, и первый
подозреваемый при расхождении с документацией инструмента.
- ловушка недоверенного каталога сохранена.
- Проверка:
- изнутри харнесса на 0.146.1: `codex --version > f` — 0 байт,
`| cat > g` — 18; `exec --json … > log` — пусто, `2>&1 | cat > log` —
7 строк с thread_id и двумя command_execution; без песочницы то же.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
82bb9f5501
commit
1538fdaf4e
1 file changed
+46
-46
@@ -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-*-<thread-id>.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 байт в каждом,
|
||||
лог через канал — семь строк.
|
||||
Reference in new issue
Block a user