diff --git a/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md b/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md index c55ea28..1edba21 100644 --- a/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md +++ b/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md @@ -52,33 +52,40 @@ WSL2 Ubuntu: exec/resume/`-o`/фоновый Bash — весь конвейер) его реальному выходу. - **О зависании фоновый запуск молчит**: он будит по выходу, а повисший тред не выходит — живой процесс и работающий процесс снаружи неразличимы. - Признак жизни — рост `stdout.jsonl`, а не статус (2026-07-07). Долгий - прогон страхуй сторожем — вторым фоновым Bash, который выходит либо когда + Признак жизни — рост JSONL-лога, а не статус (2026-07-07). Долгий прогон + страхуй сторожем — вторым фоновым Bash, который выходит либо когда появился `-o`-отчёт, либо когда лог перестал расти. Сторож ходит по артефактам, а не по pid: фоновый Bash отдаёт id задачи харнесса, а pid - процесса тебе неоткуда взять. + процесса тебе неоткуда взять. Пара файлов — **от той ветки, которую + страхуешь** (у ревью `review-impl-*`, у починки `fix-*`): подставь их в + первую строку, иначе сторож проверит чужой отчёт, найдёт его на месте и + выйдет, не сделав ни одного тика. ```bash + REPORT="$D/task-result.md"; LOG="$D/task-stdout.jsonl" # ветка исполнителя prev=-1 - while [ ! -s "$D/task-result.md" ]; do + while [ ! -s "$REPORT" ]; do sleep 300 - [ -s "$D/task-result.md" ] && break - cur=$(wc -c < "$D/task-stdout.jsonl" 2>/dev/null || echo 0) + [ -s "$REPORT" ] && break + [ -e "$LOG" ] || { echo NOLOG; break; } + cur=$(wc -c < "$LOG") [ "$cur" = "$prev" ] && { echo STALLED; break; } prev=$cur done ``` - Две ловушки, обе проверены на симуляции 2026-08-03. Выход проверяй **и - после `sleep`** — иначе сторож объявит застой ровно в тот тик, когда - Кодекс дописывал отчёт. И не переводи признак жизни на относительные - метки времени: `find -newermt '-10 minutes'` под `bfs` (подмена `find` в - части дистрибутивов) молча отдаёт пустой stdout — сторож закричит на - первом же тике. + Проверено симуляцией 2026-08-03: выход проверяй **и после `sleep`**, иначе + сторож объявит застой в тот самый тик, когда Кодекс дописывал отчёт. И не + переводи признак жизни на относительные метки времени: + `find -newermt '-10 minutes'` под `bfs` (подмена `find` в части + дистрибутивов) ругается в stderr, а в подстановку команды отдаёт пустой + stdout — ошибка проглотится, и сторож закричит на первом же тике. - `STALLED` — повод посмотреть, а не вердикт: длинная команда внутри - песочницы (сборка, тесты) событий не пишет. Разбудил — прочти последнюю - строку JSONL и решай сам. + `NOLOG` — путь неверен или запуск не состоялся: редирект создаёт лог сразу, + так что через тик его не быть не может. `STALLED` — повод посмотреть, а не + вердикт: длинная команда внутри песочницы (сборка, тесты) событий не пишет. + Разбудил — прочти последнюю строку JSONL и решай; решил, что жив, — + перезапусти сторож: выходом из цикла он страховку снял. - **thread_id — в первой строке stdout-JSONL** (`{"type":"thread.started",...}`). Забирай сразу после старта: это страховка — если процесс умер или его прибил хост, тред жив: `codex exec resume «дай финальный отчёт»`.