--- pr: 63 title: fix(agents+skills): enforce tool-usage policy across prompts and skills --- ## Что сделано - **AGENTS.md** — добавлена секция `## Tool Usage Policy` с таблицей 10 tools (commit, create_pr, create_issue, merge_pr, post_review, post_docs_review, pipeline_status, spec_status, memory_setup, tunnel). Колонки: имя tool | raw-эквивалент (заблокирован deny) | когда использовать | при сбое — STOP, репорт, НЕ fallback. Правило: "Используй tool вместо raw bash. Raw bash заблокирован deny (`opencode.json:311-314`). При сбое tool — STOP и репорт оркестратору, НЕ fallback на raw bash, НЕ импровизируй обход через `gh api`." Global copy `/root/.config/opencode/AGENTS.md` — bind-mount read-only из workspace `AGENTS.md`, обновится после merge + хост `git pull` + рестарт контейнера (см. ADR-026 Решение). - **6 skills** — raw bash заменён на tool-вызовы: - `run-pipeline/SKILL.md` Template A: `git commit` → `commit({ message })`, `gh pr create` → `create_pr({ title, body, issue_number })` - `run-pipeline/SKILL.md` Template B: `git commit` → `commit({ message })` (`git add` и `git push` оставлены — не заблокированы) - `run-pipeline/SKILL.md` Template D: `git commit` → `commit({ message: "fix(ci): ..." })` - `issue/SKILL.md`: `gh issue create` → `create_issue({ title, body, labels })` (3 места), `gh pr merge` → `merge_pr({ pr_number })` - `spec/SKILL.md:311`: `gh issue create` → `create_issue({ title, body, labels })` - `release/SKILL.md:44`, `add-skill/SKILL.md:70`, `repo-init/SKILL.md:41`: `git commit` → `commit({ message })` - **Skill `tunnel` восстановлен** — `.opencode/skills/tunnel/SKILL.md` (удалён в PR#42 как orphan; tool `tunnel` остался без skill-описания, пользователь вызывал вручную, но агент не "видел" его в контексте). Frontmatter: name: tunnel, description: "Подними cloudflare туннель когда пользователь просит 'подними тоннель', 'пробрось порт', 'tunnel'". Тело: инструкция вызывать tool `tunnel()` (1-й вызов — start, 2-й — stop, беспараметровый). ## Почему Research (subagent explore) выявил 3 gap'а в tool-usage инфраструктуре: - **Gap A**: 6 skills предписывали raw bash (`git commit`, `gh pr create`, `gh issue create`, `gh pr merge`), заблокированный deny в `opencode.json:311-314`. Симптом: subagent грузит skill → получает инструкцию нарушить permission layer → падает или импровизирует обход через `gh api` (см. memory `technical/gh-issue-create-blocked-workaround.md`). - **Gap B**: Tool failure handling ("при сбое tool — STOP, не fallback на raw bash") был только для 2 из 10 tools — `post_review` (reviewer.md:285) и `post_docs_review` (docs-reviewer.md:228). Для остальных 8 tools при сбое agent без инструкции, импровизирует. - **Gap C**: 4 tool'а не упомянуты нигде как tool — `create_issue`, `create_pr` (0 упоминаний), `tunnel` (skill удалён в PR#42, tool orphan), `memory_setup` (1 строка в `memory/SKILL.md:19`). Дополнительно: `gh pr comment*` остался в allow-list reviewer/docs-reviewer (ADR-019 отклонил strict-deny "для обратной совместимости"). Решено оставить как есть — промпт уже запрещает fallback при сбое tool, противоречие minimal. ## Pending - После merge: на хосте `git pull` + рестарт opencode-контейнера чтобы global config подхватил обновлённый `AGENTS.md` (bind-mount read-only) и восстановленный skill `tunnel` (авто-дискаверится при старте). - Зависимости: supersedes partial PR#42 (orchestration-switch) — Watch out в handoff pr-42 явно пишет "Третий PR серии: обновить промпты reviewer.md/memory-syncer.md/skills"; related PR#61 (issue #60) добавил "Tool failure handling" в reviewer.md/docs-reviewer.md для post_review/post_docs_review — этот PR расширяет на все 10 tools через единую policy в AGENTS.md. ## Watch out - `/root/.config/opencode/AGENTS.md` — bind-mount read-only из `/dev/vda1[/root/dockers/opencode-config/AGENTS.md]` (compose: `./AGENTS.md:/root/.config/opencode/AGENTS.md:ro`). В контейнере файл НЕ редактируется — изменения идут в workspace copy, после merge + host git pull + container restart подхватятся автоматически. Это symlink-эквивалент через bind-mount (issue предусматривал оба варианта). - Skill `tunnel` станет доступен только после рестарта opencode (skills загружаются при старте, см. add-skill/SKILL.md секция 3). - `gh pr comment*` в allow-list reviewer/docs-reviewer НЕ трогали — это intentional (ADR-019), не regression. - 7 оставшихся упоминаний `gh pr create|git commit -m|gh issue create|gh pr merge` в skills — это anti-instructions (упоминания в контексте "НЕ raw bash") и examples в permission-rules docs (`configure-opencode/SKILL.md:89`), не предписания. Grep на raw patterns нужно фильтровать по контексту. - Ветка создана от `main` (не `master` — master не существует в этом репо). Issue говорил "от master" — это соглашение naming, фактически main.