docs(skill): claude-subagent-playbook — прямой codex exec, уроки прогона 2026-07-09

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Dmitriy DementievandClaude Fable 5 committed 2026-07-09 20:05:37 +03:00
1 parent 35d4114ba3
commit 4e496a1548
6 files changed
+221 -103

No files matched your search

@@ -0,0 +1,95 @@
# Codex через прямой `codex exec`: рецепты и ловушки
Проверено 2026-07-09 (codex-cli 0.142.5, Windows + Git Bash); линукс-эмпирика
прогонов 07-06/07-07 шла через companion-обёртку и отражена в уроках ниже.
Прямой CLI надёжнее обёртки: её фоновая машина глючит (молчаливая подмена
анализа Кодекса своим — issue #158, ломает слепое ревью; зависшие статусы),
и её `--write`-запуски режет классификатор авторежима. Далее `$SCRATCH` =
каталог скретчпада сессии из системного промпта (не `/tmp`: под Windows
`/tmp` Git Bash — ловушка).
## Сквозные правила (любая ветка)
- **Промпт — файлом, шум — в файлы.** Промпт пиши Write'ом в `$SCRATCH` и
подавай через stdin (`-`); stdout/stderr — редиректами туда же. В контекст
оркестратора читается ровно один файл — финальный отчёт из `-o`.
- **Запуск — собственным фоновым Bash оркестратора** (`run_in_background`):
фоновый процесс детачится, живёт сквозь ходы и будит оркестратора по
выходу. Потолок 10 минут — только у фронтграундного Bash; фоновому таймаут
не нужен, `timeout NNN` вокруг codex не ставь.
- **thread_id — в первой строке stdout-JSONL** (`{"type":"thread.started",...}`).
Забирай сразу после старта: это страховка — если процесс умер или его
прибил хост, тред жив: `codex exec resume <id> «дай финальный отчёт»`.
- **resume — только по явному id.** Безадресный resume цепляет последний тред
сессии — при параллельных тредах подхватит чужой (например, read-only
ревью-тред вместо write-треда реализации).
- **Вердикт без находок — проверь лог: работа или отписка.** Дёшево:
`grep -c '"command_execution"' stdout.jsonl` (счётчик выполненных команд)
или промежуточные сообщения —
`jq -r 'select(.item.type=="agent_message") | .item.text' stdout.jsonl`.
Одна строка APPROVED при пустом счётчике — отписка, перезапускай.
- **Кросс-платформенно.** Рецепты — POSIX под Git Bash (эмпирика 2026-07-09:
`codex`, `jq`, редиректы под Windows работают). `$SCRATCH` задавай
forward-slash-путём (`/c/Users/...`), не `C:\...`; пути в аргументах
кавычь; в выводах под Windows возможны `\r`.
- **Блок классификатора — решение пользователя.** Если запуск не прошёл
permission-гейт, дай пользователю готовую команду с префиксом `!` в чат
или попроси сменить режим разрешений. Сработавший путь — прямой exec;
companion с `--write` блокируется и напрямую, и через раннера.
## Ветка «исполнитель» (пишет код)
```bash
cat "$SCRATCH/task-prompt.md" | codex exec --json \
-s workspace-write \
-c 'approval_policy="on-request"' -c 'approvals_reviewer="auto_review"' \
-o "$SCRATCH/task-result.md" - \
> "$SCRATCH/task-stdout.jsonl" 2> "$SCRATCH/task-stderr.txt"
```
- Право записи + авто-ревьюер аппрувов (`approvals_reviewer` в `--help` не
документирован, но `--strict-config` его принимает — проверено 2026-07-09;
связка отработала боевой прогон). Скоуп ограничивай промптом («коммит не
делай», границы из файла задачи), не песочницей — жёсткий read-only лишает
исполнителя тестов и поиска.
- Промпт: путь к файлу задачи; мандат — в этапе 3 SKILL.md.
- До старта сними baseline `git status --porcelain`; после — сверь отчёт
Кодекса с деревом: правок, которых он не называл, быть не должно.
## Ветка «ревьюер» (свежий тред, только чтение)
Тот же вызов, но `-s read-only` и без approvals-флагов. Свежий тред, не тот,
что писал код. В промпте — формат «только индекс находок» (SEVERITY,
файл:строка, суть, как проверить) и явная строка VERDICT.
## Ветка «триаж/починка» (тем же тредом, что писал код)
```bash
cat "$SCRATCH/fix-prompt.md" | codex exec resume --json <thread-id> \
-o "$SCRATCH/fix-result.md" - \
> "$SCRATCH/fix-stdout.jsonl" 2> "$SCRATCH/fix-stderr.txt"
```
- `resume` не принимает `-s`/`-C` — песочница и CWD наследуются от исходного
треда (write-тред остаётся write); модель наследуется, но переопределяется
`-m` при нужде.
- Промпт — индекс находок **дословно** + «закрой перечисленное, больше
ничего не меняй; отклонение — только аргументированно».
## Раннер-субагент: когда результат надо переварить
Для запуска раннер не нужен (см. сквозные правила) — он нужен, когда сырой
результат шумный и его стоит провалидировать или сжать до индекса, прежде
чем показывать оркестратору. Тогда general-purpose-субагенту отдай
**готовую команду** и правила разбора — не постановку задачи: тонкий агент,
получив постановку, реализует её сам (казус форвардера, lessons 2026-07-06).
Свой 10-минутный потолок на синхронный Bash раннер обходит отслеживаемым
ожиданием: команда запускается его собственным фоновым Bash, а ждёт он
процессом-ожидателем (`until grep -q '<маркер>' лог; do sleep 30; done` под
`run_in_background`) — харнесс переинвоцирует его по выходу процесса.
«Жду уведомления» без отслеживаемого процесса не будит никогда
(эмпирика 2026-07-07).
Companion-плагин (`codex-companion.mjs` в кэше плагинов) — только для
ручного интерактива (`status`, `result <job-id>`); конвейер ходит прямым
exec.