Files
dotfiles/agents/.agents/skills/claude-subagent-playbook/references/codex-exec.md
T

96 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.