* fix(skills): add 8th SDD heading to issue and bug-discovery * fix(skills): sync spec and audit SDD headings to 8 --------- Co-authored-by: opencode-agent <agent@opencode.local>
174 lines
No EOL
12 KiB
Markdown
174 lines
No EOL
12 KiB
Markdown
---
|
||
name: issue
|
||
description: Creates GitHub issues. Issues must be self-contained — an agent in an empty chat can execute without extra context. If a task is large, split it into smaller ones. Use a subagent for creation to avoid cluttering context. Also when user says "создай ишью", "создай issue", "заведи задачу", "разбей на подзадачи", "create issue".
|
||
---
|
||
|
||
## Принцип: один issue = один PR
|
||
|
||
Issue — это атомарная задача, выполнимая за один PR. Если задача касается > 3-5 файлов или содержит независимые изменения → разбей на несколько issue. Каждый под-issue связывается с родительским через `Part of #N`. Родительский issue закрывается только когда все под-issue смержены.
|
||
|
||
## Самодостаточность issue
|
||
|
||
Issue должно содержать всё необходимое, чтобы агент в пустом чате (без контекста предыдущей беседы) мог выполнить задачу:
|
||
|
||
- **Пути к файлам** — конкретные, с номерами строк если применимо (например `src/video_uniq/effects/camera.py:72`)
|
||
- **Что менять** — точное описание изменений, не абстрактное «улучшить» или «починить»
|
||
- **Примеры из кода** — если нужно показать паттерн, сослаться на конкретный файл и строки
|
||
- **Команды проверки** — какие команды запустить после изменений (pytest, ruff, mypy) и какой ожидаемый результат
|
||
- **Связанные ресурсы** — ссылки на связанные issue/PR (например `Ref #33`, `Closes #33`)
|
||
|
||
## Структура body
|
||
|
||
```markdown
|
||
## Контекст
|
||
Зачем: [мотивация — почему это нужно]
|
||
Контекст: [текущее состояние, что есть сейчас]
|
||
|
||
## Задача
|
||
[Что делаем — пошагово, с путями к файлам и номерами строк]
|
||
|
||
## Контракты
|
||
[Ожидаемое поведение: API, форматы запросов/ответов, коды ошибок]
|
||
|
||
## Инварианты
|
||
[Правила без исключений: лимиты, ограничения, выбранные технологии]
|
||
|
||
## Граничные случаи
|
||
[Что при ошибках: невалидный вход, отказ внешнего сервиса, превышение лимита]
|
||
|
||
## Влияние на связанные компоненты
|
||
[Связанные файлы/оракулы/агенты/промпты/валидаторы; paired updates; «нет связанных компонентов» для тривиальных задач]
|
||
|
||
## Вне scope
|
||
[Что НЕ делаем в этой итерации]
|
||
|
||
## Критерии приемки
|
||
- [ ] Проверяемый сценарий 1: "пользователь делает X → видит Y"
|
||
- [ ] Проверяемый сценарий 2
|
||
```
|
||
|
||
## Правило дробления
|
||
|
||
Перед созданием issue оцени объём:
|
||
|
||
- 1-3 файлов → один issue
|
||
- > 3-5 файлов или несколько независимых изменений → предложи пользователю разбить на несколько issue
|
||
- Каждый под-issue самодостаточен (свой контекст, свои пути, своя проверка)
|
||
- Связь через `Part of #N` (подзадача) и `Closes #N` (когда подзадача закрывает родительскую)
|
||
|
||
Пример:
|
||
|
||
> Пользователь: «Перепиши логику рендеринга, добавь кэширование и почини баг с памятью»
|
||
> Агент: «Это 3 независимые задачи. Создам 3 issue: #10 (рендеринг), #11 (кэширование), #12 (баг памяти). Каждый выполним одним PR.»
|
||
|
||
## Использование subagent для создания issue
|
||
|
||
Issue создаёт **subagent** (general type), а не основной агент. Это сохраняет контекст основного агента — длинный body issue не попадает в его историю.
|
||
|
||
**Main agent** передаёт subagent'у только **intent summary** — короткое описание задачи (1-3 предложения: что и зачем). Subagent делает всё остальное.
|
||
|
||
**Subagent (полная ответственность):**
|
||
1. Загрузи навык `issue`
|
||
2. Собери контекст — прочитай файлы из intent summary, пойми задачу, оцени объём (правило дробления ниже)
|
||
3. Составь self-contained body по шаблону (Контекст → Задача → Контракты → Инварианты → Граничные случаи → Влияние на связанные компоненты → Вне scope → Критерии приемки)
|
||
4. Запусти `create-issue({ title: "...", body: "...", labels: ["..."] })` tool (НЕ raw `gh issue create` — заблокирован deny; tool валидирует conventional title format и headings `## Контекст`/`## Задача`/`## Контракты`/`## Инварианты`/`## Граничные случаи`/`## Влияние на связанные компоненты`/`## Вне scope`/`## Критерии приемки`)
|
||
5. Верни URL созданного issue основному агенту
|
||
|
||
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
|
||
|
||
```markdown
|
||
## Контекст
|
||
Зачем: API эндпоинт /api/videos/analyze отвечает 2-5 секунд из-за повторного обращения к Claude API для тех же видео. Кеширование результата сократит время ответа до <100мс для повторных запросов.
|
||
Контекст: сейчас AnalysisService обращается к Claude API при каждом вызове, кеша нет.
|
||
|
||
## Задача
|
||
1. В `services/analysis_service.py:45` — добавить проверку кеша перед вызовом Claude API
|
||
2. В `utils/cache.py` — использовать RedisCache (уже есть в проекте)
|
||
3. TTL результата анализа — 30 дней
|
||
4. При cache hit — пропустить обращение к TranscriptService и AnalysisService
|
||
|
||
## Контракты
|
||
- POST /api/videos/analyze — без изменений в API
|
||
- При cache hit: 200 OK, время ответа <100мс
|
||
- При cache miss: 200 OK, время ответа 2-5 сек (как сейчас)
|
||
|
||
## Инварианты
|
||
- Кеш только через Redis (RedisCache из utils/cache.py)
|
||
- TTL результата анализа — 30 дней (2592000 сек)
|
||
- Невалидный ответ Claude НЕ кешируется
|
||
|
||
## Граничные случаи
|
||
- Redis недоступен → логировать warning, продолжить без кеша (cache miss)
|
||
- Кеш содержит устаревший формат → invalidate, пересчитать
|
||
- Конкурентные запросы на одно видео → первый пишет в кеш, последующие берут из кеша
|
||
|
||
## Влияние на связанные компоненты
|
||
- AnalysisController зависит от AnalysisService — без изменений (API сохранён)
|
||
- «Нет связанных компонентов» для тривиальных задач
|
||
|
||
## Вне scope
|
||
- ❌ Кеширование субтитров (отдельная задача)
|
||
- ❌ Инвалидация по времени просмотра видео
|
||
- ❌ Админ-панель для управления кешем
|
||
|
||
## Критерии приемки
|
||
- [ ] Повторный анализ того же видео → результат мгновенно (<100мс)
|
||
- [ ] Новое видео → результат через 2-5 сек (как раньше)
|
||
- [ ] Redis недоступен → API работает (без кеша), в логах warning
|
||
- [ ] pytest tests/test_analysis_service.py проходит
|
||
```
|
||
|
||
## Пример плохого issue
|
||
|
||
```markdown
|
||
**Зачем:** нужно улучшить обработку видео
|
||
**Что сделать:** переписать эффекты чтобы не падали
|
||
```
|
||
|
||
Почему плохо: нет путей к файлам, нет конкретных шагов, нет команд проверки, абстрактное описание.
|
||
|
||
## Команда создания
|
||
|
||
Через 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 содержит `## Контекст`, `## Задача`, `## Контракты`,
|
||
`## Инварианты`, `## Граничные случаи`, `## Влияние на связанные компоненты`,
|
||
`## Вне scope`, `## Критерии приемки` headings и на русском (Cyrillic
|
||
обязательна). При ошибке валидации tool возвращает ошибку и НЕ вызывает gh —
|
||
почини формат и повтори.
|
||
|
||
Label выбирай по типу задачи (совпадает с commit `type`):
|
||
- `enhancement` — новая функциональность (`feat`)
|
||
- `bug` — исправление (`fix`)
|
||
- `refactor` — рефакторинг без изменения поведения (`refactor`)
|
||
- `documentation` — доки (`docs`)
|
||
- `chore` — обслуживание, зависимости, конфиг (`chore`)
|
||
- `performance` — производительность (`perf`)
|
||
|
||
Если label не существует в репо — tool упадёт. Создай через `gh label create
|
||
<name> --color <hex>` (один раз, `gh label create` НЕ заблокирован) или
|
||
опусти labels в вызове tool.
|
||
|
||
## Пути навыков
|
||
|
||
Навыки создаются в `.opencode/skills/` в репозитории opencode-config. НЕ в `~/.config/opencode/skills/` — это маунт из репо. После изменения навыка нужен `git pull` на хосте + рестарт opencode.
|
||
|
||
## Полный workflow
|
||
|
||
После создания issue, цикл продолжается (см. `run-pipeline` skill для деталей PR процесса):
|
||
|
||
1. **Subagent** — `task(general)` читает issue, реализует, коммитит, push, создаёт PR. Оркестрация — через `run-pipeline` skill.
|
||
2. **Code review** — `@reviewer` subagent ревьюит PR (diff, skills, standards), постит `## Code Review Summary` комментарий.
|
||
3. **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.
|
||
4. **Memory-sync** — `@memory-syncer` дистиллирует PR body в `<memory_dir>/repos/{host}/{org}/{repo}.md`.
|
||
|
||
См. `AGENTS.md` (Development Workflow) и `run-pipeline` skill — все три документа описывают одну и ту же full-subagent модель делегирования. |