fix(agents+skills): enforce tool-usage policy across prompts and skills (#63)
* fix(agents): add tool usage policy to AGENTS.md * fix(skills): replace raw bash with tools in 6 skills * feat(skills): restore tunnel skill * docs(handoff): scaffold handoff and ADR for PR * docs(handoff): set PR number * docs(project-map): add tunnel skill + tool usage policy note (PR#63) --------- Co-authored-by: opencode-agent <agent@opencode.local>
This commit is contained in:
parent
f96acaaa75
commit
a2666183f8
11 changed files with 294 additions and 27 deletions
|
|
@ -67,10 +67,16 @@ Implementing agent (subagent, которому делегировано созд
|
|||
```bash
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
git add .opencode/skills/<skill-name>/SKILL.md
|
||||
git commit -m "feat(skills): add <skill-name> skill for <purpose>"
|
||||
git push
|
||||
```
|
||||
|
||||
Затем через `commit` tool (НЕ raw `git commit` — заблокирован deny):
|
||||
|
||||
```
|
||||
commit({ message: "feat(skills): add <skill-name> skill for <purpose>" })
|
||||
```
|
||||
|
||||
Затем `git push`.
|
||||
|
||||
## 5. Инструкция пользователю
|
||||
|
||||
После push сообщить пользователю:
|
||||
|
|
|
|||
|
|
@ -80,10 +80,10 @@ Issue создаёт **subagent** (general type), а не основной аг
|
|||
1. Загрузи навык `issue`
|
||||
2. Собери контекст — прочитай файлы из intent summary, пойми задачу, оцени объём (правило дробления ниже)
|
||||
3. Составь self-contained body по шаблону (Контекст → Что сделать → Проверка → Acceptance criteria → Dependencies → Связанные ресурсы)
|
||||
4. Запусти `gh issue create --title "..." --body "..."` (labels — см. guidance ниже)
|
||||
4. Запусти `create_issue({ title: "...", body: "...", labels: ["..."] })` tool (НЕ raw `gh issue create` — заблокирован deny; tool валидирует conventional title format и headings `## Контекст`/`## Задача`/`## Критерии приемки`)
|
||||
5. Верни URL созданного issue основному агенту
|
||||
|
||||
Main agent НЕ пишет body и НЕ запускает `gh issue create` — всё через subagent. Это согласовано с `run-pipeline` skill (Phase 0: "через subagent с `issue` skill") и `AGENTS.md` (Dev Workflow, step 2: "delegate to `task` subagent").
|
||||
Main agent НЕ пишет body и НЕ запускает `create_issue` — всё через subagent. Это согласовано с `run-pipeline` skill (Phase 0: "через subagent с `issue` skill") и `AGENTS.md` (Dev Workflow, step 2: "delegate to `task` subagent").
|
||||
|
||||
## Пример хорошего issue
|
||||
|
||||
|
|
@ -123,12 +123,16 @@ Zoom breathing падает при включённом geometry crop — crop
|
|||
|
||||
## Команда создания
|
||||
|
||||
```bash
|
||||
gh issue create \
|
||||
--title "type(scope): description" \
|
||||
--body "..." \
|
||||
--label "<label>"
|
||||
Через tool (НЕ raw bash — `gh issue create *` заблокирован deny):
|
||||
|
||||
```
|
||||
create_issue({ title: "type(scope): description", body: "...", labels: ["<label>"] })
|
||||
```
|
||||
|
||||
Tool валидирует: title соответствует conventional format (type(scope): desc,
|
||||
≤80 chars, English), body содержит `## Контекст`, `## Задача`, `## Критерии
|
||||
приемки` headings и на русском (Cyrillic обязательна). При ошибке валидации
|
||||
tool возвращает ошибку и НЕ вызывает gh — почини формат и повтори.
|
||||
|
||||
Label выбирай по типу задачи (совпадает с commit `type`):
|
||||
- `enhancement` — новая функциональность (`feat`)
|
||||
|
|
@ -138,7 +142,9 @@ Label выбирай по типу задачи (совпадает с commit `t
|
|||
- `chore` — обслуживание, зависимости, конфиг (`chore`)
|
||||
- `performance` — производительность (`perf`)
|
||||
|
||||
Если label не существует в репо — `gh issue create` упадёт. Создай через `gh label create <name> --color <hex>` (один раз) или опусти `--label`.
|
||||
Если label не существует в репо — tool упадёт. Создай через `gh label create
|
||||
<name> --color <hex>` (один раз, `gh label create` НЕ заблокирован) или
|
||||
опусти labels в вызове tool.
|
||||
|
||||
## Пути навыков
|
||||
|
||||
|
|
@ -151,7 +157,9 @@ Label выбирай по типу задачи (совпадает с commit `t
|
|||
1. **Subagent** — `task(general)` читает issue, реализует, коммитит, push, создаёт PR. Оркестрация — через `run-pipeline` skill.
|
||||
2. **Docs review** — `@docs-reviewer` subagent валидирует handoff + ADR, обновляет project map (pre-merge).
|
||||
3. **Code review** — `@reviewer` subagent ревьюит PR (diff, skills, standards), постит `## Code Review Summary` комментарий.
|
||||
4. **Merge or Repeat** — APPROVE → `gh pr merge N --squash --delete-branch` (после CI ✅); замечания → fix subagent → re-review → merge.
|
||||
4. **Merge or Repeat** — APPROVE → `merge_pr({ pr_number: N })` tool (squash +
|
||||
delete branch, без `--admin`; НЕ raw `gh pr merge` — заблокирован deny),
|
||||
после CI ✅; замечания → fix subagent → re-review → merge.
|
||||
5. **Memory-sync** — `@memory-syncer` дистиллирует handoff + ADR в `app_data/opencode-memory/repos/{host}/{org}/{repo}.md`.
|
||||
|
||||
См. `AGENTS.md` (Development Workflow) и `run-pipeline` skill — все три документа описывают одну и ту же full-subagent модель делегирования.
|
||||
|
|
@ -41,7 +41,12 @@ description: Выполняет релиз после мерджа PR — обн
|
|||
|
||||
```bash
|
||||
git add CHANGELOG.md
|
||||
git commit -m "docs: add vX.Y.Z changelog entry"
|
||||
```
|
||||
|
||||
Затем через `commit` tool (НЕ raw `git commit` — заблокирован deny):
|
||||
|
||||
```
|
||||
commit({ message: "docs: add vX.Y.Z changelog entry" })
|
||||
```
|
||||
|
||||
### Шаг 5: Создать tag
|
||||
|
|
|
|||
|
|
@ -38,7 +38,12 @@ description: Sequential checklist: create GitHub remote → configure settings/b
|
|||
git init
|
||||
echo "# <repo-name>" > README.md
|
||||
git add README.md
|
||||
git commit -m "chore: initial commit"
|
||||
```
|
||||
|
||||
Затем через `commit` tool (НЕ raw `git commit` — заблокирован deny):
|
||||
|
||||
```
|
||||
commit({ message: "chore: initial commit" })
|
||||
```
|
||||
|
||||
Если bare-repo без initial commit — `gh repo create --source=.` создаст remote, но push будет пустым, а main branch не появится → branch protection упадёт.
|
||||
|
|
|
|||
|
|
@ -47,13 +47,15 @@ description: Автономный исполнитель PR-пайплайна.
|
|||
зафикь и продолжай — не додумывай.
|
||||
3. Создай handoff + ADR: `bash .opencode/scripts/scaffold-handoff.sh M <slug>`
|
||||
(M — будет PR номер, используй placeholder `<PR-NUMBER>` в handoff
|
||||
frontmatter, потом исправишь после `gh pr create`).
|
||||
4. Коммиты в формате `type(scope): description` (≤72 chars, English, no
|
||||
period, no body unless necessary). Минимум 3-4 логических коммита.
|
||||
5. Push и создай PR:
|
||||
`gh pr create --title "type(scope): description" --body "## Что сделано\n...\n\n## Почему\n...\n\nCloses #N"`
|
||||
frontmatter, потом исправишь после create_pr).
|
||||
4. Коммиты через `commit({ message: "type(scope): description" })` tool (НЕ
|
||||
raw `git commit` — заблокирован deny). Формат: ≤72 chars, English, no
|
||||
period, no body unless necessary. Минимум 3-4 логических коммита.
|
||||
5. Push ветку (`git push -u origin HEAD`), затем создай PR через tool:
|
||||
`create_pr({ title: "type(scope): description", body: "## Что сделано\n...\n\n## Почему\n...\n\nCloses #N", issue_number: N })`.
|
||||
6. После получения PR номера — исправь placeholder `<PR-NUMBER>` в handoff
|
||||
frontmatter, отдельный коммит `docs(handoff): set PR number`, push.
|
||||
frontmatter, отдельный коммит `docs(handoff): set PR number` через
|
||||
`commit` tool, push.
|
||||
7. Верни PR номер M.
|
||||
```
|
||||
|
||||
|
|
@ -69,8 +71,9 @@ Review PR#M в текущем репо (pre-merge, режим docs).
|
|||
5. Валидируй ADR `docs/decisions/*-pr-M-*.md`: 4 секции (Статус, Контекст,
|
||||
Решение, Альтернативы).
|
||||
6. Если криво — почини (edit: allow).
|
||||
7. `git add docs/project-map/ docs/handoff/ docs/decisions/ && git commit -m
|
||||
"docs: update project map + handoff + ADR" && git push`.
|
||||
7. `git add docs/project-map/ docs/handoff/ docs/decisions/` (add — НЕ
|
||||
заблокирован), затем `commit({ message: "docs: update project map + handoff + ADR" })`
|
||||
tool, и `git push`.
|
||||
8. **ВСЕГДА** оставь PR comment (даже если structural changes нет) — это
|
||||
детерминированный marker для `check_docs` в pipeline-status.py. Без comment
|
||||
pipeline блокируется на DOCS phase. Используй tool `post_docs_review` (НЕ
|
||||
|
|
@ -113,7 +116,8 @@ Log: `gh run view <run-id> --log-failed` output:
|
|||
1. `gh pr checkout M`.
|
||||
2. Проанализируй log, найди причину.
|
||||
3. Исправь (минимальные изменения, whitespace/formatting/logic fix).
|
||||
4. Коммит `fix(ci): <description>`, push.
|
||||
4. Коммит через `commit({ message: "fix(ci): <description>" })` tool (НЕ raw
|
||||
`git commit`), push.
|
||||
5. Не трогай логику unrelated файлов.
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -308,8 +308,8 @@ Default stack для типа (хардкод, добавить всегда):
|
|||
## Связанные ресурсы (Part of spec, ref к docs/spec/roadmap.md)
|
||||
- Issue #1 (scaffolding) body ДОЛЖЕН включать:
|
||||
"Используй repo-init skill для: pyproject.toml, CI, .gitignore, LICENSE, dependabot, pre-commit. Структура — из ## Структура в docs/spec/modules.md."
|
||||
- gh issue create --title "type(scope): description" --body "<body>" --label "enhancement,from-spec"
|
||||
4. Собери реальные номера issues из вывода gh.
|
||||
- `create_issue({ title: "type(scope): description", body: "<body>", labels: ["enhancement", "from-spec"] })` tool (НЕ raw `gh issue create` — заблокирован deny)
|
||||
4. Собери реальные номера issues из вывода tool.
|
||||
5. Update docs/spec/roadmap.md: добавь реальные #N номера. Update docs/spec/meta.md: executed=true, phase=8.
|
||||
6. Верни: [{number, url, title}, ...] для всех issues.
|
||||
```
|
||||
|
|
|
|||
13
.opencode/skills/tunnel/SKILL.md
Normal file
13
.opencode/skills/tunnel/SKILL.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
name: tunnel
|
||||
description: Подними cloudflare туннель когда пользователь просит "подними тоннель", "пробрось порт", "tunnel"
|
||||
---
|
||||
|
||||
# Tunnel
|
||||
|
||||
Когда пользователь просит поднять или опустить cloudflare тоннель — вызови
|
||||
tool `tunnel()`. Первый вызов — старт, второй — стоп. Tool беспараметровый.
|
||||
|
||||
Не используй raw bash `bash .opencode/scripts/tunnel.sh` — заблокирован deny
|
||||
(см. `opencode.json:311-314`). При сбое tool — STOP и репорт оркестратору, НЕ
|
||||
fallback на raw bash.
|
||||
23
AGENTS.md
23
AGENTS.md
|
|
@ -27,6 +27,29 @@ All PR work runs through `/run-pipeline`. Pipeline phases orchestrated by `pipel
|
|||
- No comments unless explicitly requested
|
||||
- Match surrounding code style (imports, naming, patterns)
|
||||
|
||||
## Tool Usage Policy
|
||||
|
||||
Используй tool вместо raw bash. Raw bash-эквиваленты заблокированы deny
|
||||
(`opencode.json:311-314`). При сбое tool — STOP и репорт оркестратору, НЕ
|
||||
fallback на raw bash, НЕ импровизируй обход через `gh api`.
|
||||
|
||||
| Tool | Raw bash (заблокирован deny) | Когда использовать | При сбое — STOP, репорт, НЕ fallback |
|
||||
|---|---|---|---|
|
||||
| `commit({ message })` | `git commit *` | Коммит staged файлов (conventional format валидируется tool'ом) | Сообщи оркестратору, не `git commit` |
|
||||
| `create_pr({ title, body, issue_number })` | `gh pr create *` | Создание PR после push ветки | Сообщи оркестратору, не `gh pr create`, не `gh api repos/*/pulls` |
|
||||
| `create_issue({ title, body, labels })` | `gh issue create *` | Создание GitHub issue (валидация формата) | Сообщи оркестратору, не `gh issue create`, не `gh api repos/*/issues` |
|
||||
| `merge_pr({ pr_number })` | `gh pr merge *` | Merge PR (squash + delete branch, без `--admin`) | Сообщи оркестратору, не `gh pr merge` |
|
||||
| `post_review({ pr_number, verdict, body })` | `gh pr comment` для verdict | Code review verdict (heading `## Code Review Summary` + verdict) | Сообщи оркестратору, не `gh pr comment` |
|
||||
| `post_docs_review({ pr_number, verdict, body })` | `gh pr comment` для verdict | Docs review verdict (heading `## Docs Review Summary` + verdict) | Сообщи оркестратору, не `gh pr comment` |
|
||||
| `pipeline_status({ pr_number })` | `python3 .opencode/scripts/pipeline-status.py` | Read-only oracle: статус фаз PR + NEXT action | Сообщи оркестратору, не bash-запуск скрипта |
|
||||
| `spec_status({})` | `python3 .opencode/scripts/spec-status.py` | Read-only oracle: текущая фаза spec + NEXT action | Сообщи оркестратору, не bash-запуск скрипта |
|
||||
| `memory_setup()` | `bash .opencode/scripts/setup-memory.sh` | Инициализация/синхронизация opencode-memory (clone + hook + reindex) | Сообщи оркестратору, не bash-запуск скрипта |
|
||||
| `tunnel()` | `bash .opencode/scripts/tunnel.sh` | Cloudflare tunnel toggle (1-й вызов — start, 2-й — stop) | Сообщи оркестратору, не bash-запуск скрипта |
|
||||
|
||||
`gh pr comment*` остаётся в allow-list reviewer/docs-reviewer для обратной
|
||||
совместимости (ADR-019 отклонил strict-deny). Промпт уже запрещает fallback при
|
||||
сбое tool — противоречие minimal.
|
||||
|
||||
## Language
|
||||
|
||||
- Always respond to the user in Russian.
|
||||
116
docs/decisions/026-pr-63-enforce-tool-usage-policy.md
Normal file
116
docs/decisions/026-pr-63-enforce-tool-usage-policy.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# ADR-026: Enforce tool-usage policy across prompts and skills
|
||||
|
||||
## Статус
|
||||
|
||||
Accepted (2026-07-25)
|
||||
|
||||
## Контекст
|
||||
|
||||
Research (subagent explore) выявил 3 gap'а в tool-usage инфраструктуре репо
|
||||
`slaid098/opencode-config`:
|
||||
|
||||
### Gap A: Skills предписывают raw bash, заблокированный deny-правилами
|
||||
|
||||
6 skill-файлов предписывали subagent'ам raw bash команды, которые глобально
|
||||
заблокированы в `opencode.json:311-314` (4 deny-правила: `git commit *`,
|
||||
`gh pr create *`, `gh pr merge *`, `gh issue create *`):
|
||||
|
||||
- `run-pipeline/SKILL.md` Template A: `gh pr create`, `git commit`
|
||||
- `run-pipeline/SKILL.md` Template B/D: `git commit`
|
||||
- `issue/SKILL.md:83,127`: `gh issue create`; `:154`: `gh pr merge`
|
||||
- `spec/SKILL.md:311`: `gh issue create`
|
||||
- `release/SKILL.md:44`, `add-skill/SKILL.md:70`, `repo-init/SKILL.md:41`:
|
||||
`git commit`
|
||||
|
||||
Симптом: subagent грузит skill → получает инструкцию нарушить permission
|
||||
layer → падает (deny блокирует bash) или импровизирует обход через `gh api`
|
||||
(см. memory `technical/gh-issue-create-blocked-workaround.md` — `gh api
|
||||
repos/*/issues` allow-rule существует, но использование его для создания
|
||||
issue обходит валидацию тулзы и ломает формат репо).
|
||||
|
||||
### Gap B: Tool failure handling только для 2 из 10 tools
|
||||
|
||||
Секция "Tool failure handling" (инструкция "при сбое tool — STOP, не fallback
|
||||
на raw bash") была только для `post_review` (`reviewer.md:285`) и
|
||||
`post_docs_review` (`docs-reviewer.md:228`). Для `commit`, `create_pr`,
|
||||
`create_issue`, `merge_pr`, `pipeline_status`, `spec_status`, `memory_setup`,
|
||||
`tunnel` — отсутствует. При сбое agent без инструкции, импровизирует.
|
||||
|
||||
### Gap C: 4 tool'а не упомянуты нигде как tool
|
||||
|
||||
- `create_issue`, `create_pr` — 0 упоминаний как tool в промптах/skills
|
||||
(только raw `gh issue create`/`gh pr create` в skills, заблокированные deny)
|
||||
- `tunnel` — skill удалён в PR#42 (orchestration-switch), tool остался orphan
|
||||
(0 упоминаний как tool; пользователь использует вручную, но агент не
|
||||
"видит" его в контексте)
|
||||
- `memory_setup` — 1 строка в `memory/SKILL.md:19`, в промптах агентов нет
|
||||
|
||||
### Дополнительно
|
||||
|
||||
`gh pr comment*` остался в allow-list reviewer/docs-reviewer (ADR-019
|
||||
отклонил strict-deny "для обратной совместимости"). Решено: оставить в allow
|
||||
(промпт уже запрещает fallback при сбое tool, противоречие minimal).
|
||||
|
||||
## Решение
|
||||
|
||||
### 1. AGENTS.md: единая Tool Usage Policy секция
|
||||
|
||||
В `AGENTS.md` добавлена секция `## Tool Usage Policy` с таблицей всех 10
|
||||
tools. Колонки: имя tool | raw-эквивалент (заблокирован deny) | когда
|
||||
использовать | при сбое — STOP, репорт, НЕ fallback. Правило: "Используй tool
|
||||
вместо raw bash. Raw bash-эквиваленты заблокированы deny
|
||||
(`opencode.json:311-314`). При сбое tool — STOP и репорт оркестратору, НЕ
|
||||
fallback на raw bash, НЕ импровизируй обход через `gh api`."
|
||||
|
||||
Это устраняет Gap B (единая policy для всех 10 tools вместо per-tool
|
||||
инструкций) и Gap C (4 tool'а теперь упомянуты как tool в едином месте).
|
||||
|
||||
Global copy `/root/.config/opencode/AGENTS.md` — bind-mount read-only из
|
||||
workspace `AGENTS.md` (compose: `./AGENTS.md:/root/.config/opencode/AGENTS.md:ro`).
|
||||
В контейнере файл не редактируется; изменения идут в workspace copy, после
|
||||
merge + host `git pull` + container restart подхватываются автоматически. Это
|
||||
symlink-эквивалент через bind-mount.
|
||||
|
||||
### 2. 6 skills: raw bash → tool-вызовы
|
||||
|
||||
Все предписания raw bash в 6 skills заменены на tool-вызовы (см. handoff "Что
|
||||
сделано" для полного списка). `git add` и `git push` оставлены — они не
|
||||
заблокированы deny. Anti-instructions (упоминания "НЕ raw bash") сохранены
|
||||
как документация.
|
||||
|
||||
### 3. Skill `tunnel` восстановлен
|
||||
|
||||
Создан `.opencode/skills/tunnel/SKILL.md` (удалён в PR#42, tool остался
|
||||
orphan). Frontmatter: name: tunnel, description с триггерами "подними
|
||||
тоннель"/"пробрось порт"/"tunnel". Тело: инструкция вызывать tool `tunnel()`
|
||||
(1-й вызов — start, 2-й — stop, беспараметровый). Skill станет доступен
|
||||
после рестарта opencode (skills загружаются при старте).
|
||||
|
||||
### 4. `gh pr comment*` оставлен в allow-list
|
||||
|
||||
Не трогали — intentional (ADR-019). Промпт уже запрещает fallback при сбое
|
||||
tool (`post_review`/`post_docs_review`), противоречие minimal. strict-deny
|
||||
`gh pr comment*` отклонён (см. Альтернативы).
|
||||
|
||||
## Альтернативы
|
||||
|
||||
- **Per-agent промпты: добавить tool failure handling в каждый agent.md
|
||||
по отдельности** — отклонено из-за дублирования. 4 agent-файла × 10 tools =
|
||||
40 упоминаний, дрейф при добавлении новых tools. Единая policy в AGENTS.md
|
||||
(грузится всеми агентами) — canonical источник, добавление нового tool =
|
||||
1 строка в таблице.
|
||||
|
||||
- **strict-deny `gh pr comment*` (принудить к `post_review`/`post_docs_review`)** —
|
||||
отклонено (повторяет ADR-019). `gh pr comment*` остаётся в allow-list для
|
||||
обратной совместимости; tools используют spawnSync напрямую (не через bash
|
||||
permission layer), raw `gh pr comment*` не конфликтует. Промпт уже запрещает
|
||||
fallback при сбое tool — этого достаточно.
|
||||
|
||||
- **Упомянуть 4 orphan tool'а (Gap C) в per-agent промптах** — отклонено по
|
||||
той же причине дублирования. Единая таблица в AGENTS.md покрывает все 10
|
||||
tools одним источником правды.
|
||||
|
||||
- **Удалить skill `tunnel` совсем (tool orphan → удалить tool)** — отклонено:
|
||||
tool `tunnel` используется пользователем вручную и в pipeline (tunnel.sh
|
||||
scaffold). Восстановление skill даёт агенту контекст для вызова tool'а
|
||||
по триггерам пользователя.
|
||||
86
docs/handoff/pr-63-enforce-tool-usage-policy.md
Normal file
86
docs/handoff/pr-63-enforce-tool-usage-policy.md
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
---
|
||||
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.
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
opencode-config — Docker-based AI coding assistant with persistent memory (opencode configuration). Runs in Docker via `docker-compose.yml` (dind + opencode services).
|
||||
|
||||
Root `AGENTS.md` — orchestrator directive (chat = plan only, all via subagents) + global rules (pipeline, code style, language RU). Formats enforced by tools (commit/create_pr/create_issue). Auto-loaded for project + bind-mounted globally in container — PR#31.
|
||||
Root `AGENTS.md` — orchestrator directive (chat = plan only, all via subagents) + global rules (pipeline, code style, language RU) + `## Tool Usage Policy` (таблица 10 tools: commit/create_pr/create_issue/merge_pr/post_review/post_docs_review/pipeline_status/spec_status/memory_setup/tunnel; raw bash заблокирован deny, при сбое tool — STOP, НЕ fallback). Auto-loaded for project + bind-mounted globally in container — PR#31, PR#63.
|
||||
|
||||
## Structure
|
||||
|
||||
|
|
@ -35,6 +35,7 @@ opencode-config/
|
|||
│ │ ├── python-development/SKILL.md # Python dev patterns
|
||||
│ │ ├── release/SKILL.md # Tag + GitHub Release
|
||||
│ │ ├── repo-init/SKILL.md # New repository bootstrap
|
||||
│ │ ├── tunnel/SKILL.md # Cloudflare tunnel toggle (tool `tunnel()`: 1-й вызов start, 2-й stop) — PR#63 (восстановлен, удалён в PR#42)
|
||||
│ │ ├── run-tests/SKILL.md # Test runner guide
|
||||
│ │ └── spec/SKILL.md # 9-phase spec generation
|
||||
│ ├── tools/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue