* fix(agents): remove invalid top-level doom_loop field from frontmatter * fix(reviewer): simplify setup step 5 and add investigation budget * test(agents): add frontmatter validation tests * docs(handoff): add handoff and ADR-020 for doom_loop frontmatter fix * docs(handoff): set PR number * docs: update project map --------- Co-authored-by: opencode-agent <agent@slaid098.dev>
6.2 KiB
| pr | title |
|---|---|
| 49 | remove invalid doom_loop frontmatter field + simplify reviewer setup |
PR #49: remove invalid doom_loop frontmatter field + simplify reviewer setup
Что сделано
.opencode/agents/reviewer.md:6— удалён top-leveldoom_loop: deny(ВНЕ блокаpermission:). Невалидное поле — не в схемеAgentV2.Infoopencode, форвардилось провайдеру как model param →AI_APICallError: Extra inputs are not permittedна строгих провайдерах (umans-ai-coding-plan)..opencode/agents/docs-reviewer.md:6— удалён top-leveldoom_loop: deny(тот же fix)..opencode/agents/memory-syncer.md:6— удалён top-leveldoom_loop: deny(тот же fix).permission.doom_loop: denyВНУТРИ блокаpermission:— сохранён во всех 3 файлах (валидный permission guard, не тронут).steps: 100— не изменён во всех 3 файлах.reviewer.mdSetup шаг 5 — упрощён: убрана inline-ссылка на ADR-019 и детальное объяснение запретаgh pr checks/python3 pipeline-status.py. Заменено на лаконичную инструкцию сpipeline_statustool +gh run listfallback + явным "Do NOT". Это устраняет self-referential trigger (модель зацикливалась на верификации ADR-019 ссылки — 75 повторенийgit show f06c9f2 | grep ADR-019за 6 минут, doom loop отменён на step 88).reviewer.md— добавлена секция## Investigation Budgetпосле Setup: максимум ~15 steps для investigation, после чего обязательныйpost_reviewдаже при неполном review. Предотвращает бесконечные investigation loops.tests/test_agent_frontmatter.py— 6 новых тестов: frontmatter НЕ содержит top-leveldoom_loop(parsed + raw check),permission.doom_loop: denyприсутствует во всех 3 файлах,steps: 100присутствует, frontmatter parseable. Парсинг ручной (pyyaml не в зависимостях), по паттернуcheck-permissions.py(split по---, отслеживание отступов).- ADR-020 + этот handoff
Почему
При review PR #46 (reviewer ревьюил свой собственный .md файл) reviewer agent ушёл в doom loop — 75 повторений git show f06c9f2 | grep ADR-019 за 6 минут, отменён пользователем на step 88. Investigation выявило 2 проблемы:
-
doom_loop: denyкак top-level frontmatter поле — НЕ в схемеAgentV2.Infoopencode, форвардится провайдеру как model param →AI_APICallErrorна строгих провайдерах. Валидно только внутри блокаpermission:. Подтверждено логомopencode.log:91717. Top-level поле — копия permission guard, ошибочно продублированная на верхний уровень (вероятно при миграции config/ → .opencode/ в PR#23). -
Self-referential trigger — Setup шаг 5 в reviewer.md содержал inline-ссылку на ADR-019 и детальное объяснение запрета. Модель зациклилась на верификации этой ссылки (читает reviewer.md → видит ADR-019 → идёт проверять ссылку → повторяет). Это "крючок", за который модель зацепилась в doom loop.
Решение: удалить невалидное top-level поле (fix root cause #1) + упростить Setup шаг 5 (убрать self-referential hook, fix root cause #2) + добавить Investigation Budget секцию (structural guard против doom loops — явный step limit).
Pending
— (нет)
Watch out
- Top-level
doom_loopудалён, НЕpermission.doom_loop—doom_loop: denyвнутри блокаpermission:(отступ 2 пробела, строки 8/8/8) — ОСТАВЛЕН во всех 3 файлах. Это валидный permission guard. Удалён только top-leveldoom_loop: deny(indent 0, строка 6). Тестыtest_permission_doom_loop_present+test_no_top_level_doom_loopявно различают эти два поля. - Global config (OLD repo) НЕ обновлён — bind-mounted
/root/.config/opencode/agents/*.md(из/root/workspace/opencode/config/agents/) всё ещё содержит top-leveldoom_loop(commit 38c5a34 фиксил только NEW repo.opencode/agents/). Если strict provider используется в репо БЕЗ project-local agents → falls back to global → bug resurfaces. Это known issue (см. memory: technical/opencode-agent-loading-precedence.md), вне scope этого PR. - Investigation Budget — soft guard — секция в промпте reviewer.md, не type system. Модель может игнорировать ~15 step limit (как игнорирует другие промпт-правила). Но explicit limit лучше implicit — даёт модели чёткий сигнал "остановись и вызови post_review". Hard guard = steps: 100 (frontmatter) — на нём модель упрётся в лимит в любом случае.
- Setup шаг 5 упрощён, НЕ удалён —
gh pr checks(403) иpython3 pipeline-status.py(denied) запреты сохранены в лаконичной форме ("Do NOT use ..."). Запреты функциональны (permission rules в frontmatter + DANGEROUS_PATTERNS в check-permissions.py), inline-ссылка на ADR-019 — единственное убранное (она была self-referential hook, не функциональным guard). - ADR number = sequential (020), НЕ PR number (эволюция известного паттерна PR#26 docs-reviewer typo).