---
name: minor-defect-fix
description: >
  End-to-end рабочий процесс для устранения минорного дефекта из Jira: разобрать задачу,
  починить код, актуализировать и дописать тесты до покрытия 80%, обновить спецификацию
  в отдельном репо, подготовить отчёт в Jira и аккуратно закоммитить с возможностью
  создания PR в Bitbucket. Используй этот скилл, когда пользователь говорит "почини баг
  из jira", "исправь дефект", "fix STOR-123", "посмотри задачу в джире и поправь",
  "minor bug", "сделай задачу по тикету", или передаёт ключ Jira-задачи и просит её
  закрыть. Скилл сам решает, когда задать вопрос, а когда действовать — но никогда не
  коммитит и не пушит без явного согласия.
---

# Minor Defect Fix

Скилл ведёт цикл: **Jira → понять → починить → тесты → спека → коммит → PR → отчёт**.

Каждый шаг автономен ровно до точки, где нужна судьба пользователя: подтвердить план,
запушить ветку, отправить комментарий в Jira, закоммитить, создать PR. Не ускоряй эти
моменты — лучше сделать паузу и спросить, чем сделать необратимое действие "молча".

---

## 0. Предусловия и контекст

Скилл рассчитан на:
- Java/Spring Boot проект (gradle или maven), но шаги общие — Java-специфика только в
  командах сборки и в инструменте покрытия (JaCoCo).
- Подключенные MCP-серверы для **Atlassian (Jira)** и **Bitbucket**. Точные имена
  инструментов отличаются у разных серверов — ищи доступные инструменты вида
  `mcp__atlassian__*` / `mcp__jira__*` и `mcp__bitbucket__*`. Если ни один не подключен,
  останови работу и сообщи пользователю, что MCP не настроен.
- Текущая рабочая директория — корень репозитория кода. Все команды git/gradle/maven
  по умолчанию запускаются оттуда.

Если пользователь не передал ключ Jira-задачи (например, `STOR-123`) — спроси один раз
и валидируй формат (`[A-Z]+-\d+`).

---

## 1. Архитектура: кто что делает

Работа разделена тремя слоями: **главный агент**, **два вложенных скилла** и **три
типа субагентов**. Это даёт:

1. Контекст главного агента не засоряется длинными выводами `gradle test`, дампами
   покрытия и тяжёлыми чтениями документации/спеки (это уходит субагентам).
2. Анализ и реализация — вложенные скиллы, у каждого свой набор правил и автономный
   режим использования.
3. Главный агент сохраняет контроль над всем, что необратимо: коммит, push, общение
   с Jira.

| Этап | Кто исполняет | Механизм |
|---|---|---|
| Конфиг, чтение Jira | главный агент | — |
| Скоуп-чек | главный агент | — |
| **Анализ задачи и кода** | **defect-analyzer** | вложенный скилл |
| План фикса | главный агент | — |
| **Правка кода** | **bugfix-developer** | вложенный скилл |
| **Написание/актуализация тестов** | тестописатель | субагент general-purpose |
| **Прогон тестов и покрытия** | тестраннер | субагент general-purpose |
| Pre-commit (build + lint + coverage) | тестраннер | субагент general-purpose |
| **Обновление спецификации (отдельное репо)** | спецадаптер | субагент general-purpose |
| Просмотр диффа спеки, push/PR спеки | главный агент | — |
| Коммит кода | главный агент | — |
| PR кода | главный агент | — |
| Финальный отчёт в Jira | главный агент | — |

**Вложенный скилл vs субагент.** Скилл загружается в контекст главного агента — он сам
действует по инструкциям. Субагент работает в изолированном контексте и возвращает
структурированный отчёт. Скиллы выбраны для шагов с тесной интеракцией с пользователем
(анализ может задать уточняющие вопросы; разработчик может попросить подтвердить
edge case). Субагенты — для шагов с тяжёлым выводом (gradle, JaCoCo, скан спеки).

**Важно:** субагентов вызывай в момент, когда они нужны. Каждый вызов передаёт ровно
тот контекст, который нужен для его задачи. Шаблоны промптов — ниже.

---

## 2. Конфиг скилла (документация проекта и репо спецификации)

Скилл хранит маппинг "корень репозитория кода → путь к репо спецификации" в
`~/.claude/skills/minor-defect-fix/config.json`. Путь спеки — это **корень git-репо
со спецификацией в .md** (там должен быть `.git`).

```json
{
  "projects": {
    "/Users/.../StorageService": {
      "docs_path": "/Users/.../StorageService-spec"
    }
  }
}
```

**Алгоритм:**
1. Возьми абсолютный путь текущего репозитория (`git rev-parse --show-toplevel`).
2. Прочитай конфиг. Если файла нет — считай, что конфиг пустой.
3. Если для текущего корня есть запись и путь существует и в нём есть `.git` —
   используй её.
4. Иначе спроси у пользователя: "Где лежит git-репо со спецификацией проекта (.md)?".
   Прими как абсолютный или ~-путь. Проверь, что:
   - папка существует,
   - содержит `.git` (это git-репо),
   - содержит хотя бы один `.md`.
   Сохрани в конфиг.

Не читай документацию сам — это сделают субагенты-аналитик и спецадаптер. Главному
агенту достаточно знать путь.

---

## 3. Получить задачу Jira

Через MCP получи: `summary`, `description`, `issuetype`, `priority`, `status`,
последние комментарии (5-10), `attachments` (хотя бы имена). Сохрани этот объект в
переменную для передачи субагентам.

### Скоуп-чек (важно)
Это скилл для **минорных** правок. Если выполняется хотя бы одно условие — **останови
работу и спроси пользователя, действительно ли это та задача**, прежде чем продолжать:

- `priority` ∈ {Major, Critical, Blocker, Highest}
- `issuetype` ∈ {Epic, Story, New Feature}
- описание задачи содержит явные слова `breaking change`, `migration`, `refactor`,
  `redesign`, `архитектур`, `переписать`, `новая фича`
- описание содержит больше одного независимого сценария ("и ещё", "а также", несколько
  AC)

Покажи свой повод для сомнений и спроси:
> "Задача выглядит крупнее, чем минорный дефект (причина: ...). Продолжить или остановиться?"

---

## 4. Анализ — вложенный скилл defect-analyzer

Подгрузи в контекст инструкции аналитика:

```
Skill(skill='defect-analyzer')
```

Передай ему в текстовом виде: объект Jira (summary, description, последние 3-5
комментариев), корень репо кода (`git rev-parse --show-toplevel`), путь к репо спеки
(`docs_path` из конфига).

defect-analyzer сам:
- Прогрепит код прицельно по именам классов/методов/ошибок из задачи.
- Найдёт затронутые тесты (только имена, не содержимое).
- Найдёт затронутые разделы спеки в `docs_path` (или зафиксирует, что нет).
- Выдаст структурированный отчёт (что/где/root cause/тесты/спека/edge cases).

Если defect-analyzer возвращает открытые вопросы — передай их пользователю одним
сообщением и продолжи только после ответа. Если отчёт полный — переходи к плану.

---

## 5. План фикса

Прежде чем менять код, изложи **короткий план** на основе отчёта аналитика:
- Какой файл(ы) ты собираешься менять и зачем.
- Какое изменение в одном-двух предложениях.
- Что станет с тестами и со спекой (на этом этапе — гипотеза).

Спроси: "Делаем так?". Менять код начинай только после подтверждения.

---

## 6. Реализация фикса — вложенный скилл bugfix-developer

После одобренного плана подгрузи разработчика:

```
Skill(skill='bugfix-developer')
```

Передай ему: отчёт от defect-analyzer (или его суть в одном абзаце), утверждённый
план, ключ Jira-задачи.

bugfix-developer задаёт **принципы багфикса** (минимальное изменение, сохранение
сигнатур, стиль файла важнее личных привычек, edge cases фиксим сразу) и проводит
главного агента через чек-лист правки. Сами Edit/Write остаются за главным агентом —
diff виден пользователю.

**Когда подключать java-spring-dev параллельно.** Если по ходу фикса появляются вопросы
по конвенциям проекта (нужная Lombok-аннотация, правильное место для нового исключения
в пакетной структуре, формат DTO) — вызови:

```
Skill(skill='java-spring-dev')
```

Не подключай его наперёд — это лишний контекст. Только когда конкретно потребовался
ответ "как принято в этом проекте".

---

## 7. Тесты — два субагента

### 7.1. Субагент-тестописатель

Зови сразу после того, как код фикса сохранён. Передавай ему точный текущий diff.

```
description: "Update and write tests for <JIRA-KEY> fix"
subagent_type: general-purpose

prompt:
Главный агент только что внёс фикс. Твоя задача — привести тесты к актуальному виду
и добиться покрытия изменённых файлов ≥ 80% (line coverage по JaCoCo).

Корень проекта: <git toplevel>
Изменённые в фиксе файлы: <список путей>
Diff фикса:
<git diff HEAD>

Существующие тесты для затронутых классов (пути): <пути>

Контекст задачи Jira:
- <summary>
- <core description>

Алгоритм:
1. Для каждого упавшего/устаревшего теста реши: тест устарел (правь тест) или фикс
   что-то ломает (СТОП, верни это в отчёте, не редактируй).
2. Допиши тесты на новые ветки кода из фикса (особенно edge cases — null, пустые, граница).
3. Соблюдай стиль соседних тестов: имена методов, given/when/then, моки, фикстуры.
4. Не запускай тесты — этим займётся другой агент.
5. Не трогай тесты, не связанные с изменёнными файлами.

Верни (≤200 слов):
- Список созданных файлов тестов с краткой целью каждого.
- Список изменённых тестов с диагностикой.
- Список тестов, в которых ты НЕ уверен (фикс может быть некорректен).
```

После ответа главный агент читает diff (`git diff src/test/`) и при «неуверенных»
тестах пересматривает фикс.

### 7.2. Субагент-тестраннер

Зови сразу после тестописателя. Этот агент только запускает.

```
description: "Run tests and JaCoCo for changed files"
subagent_type: general-purpose

prompt:
Запусти тесты и JaCoCo, верни структурированный отчёт.

Корень проекта: <git toplevel>
Тип сборки: <gradle | maven — определи по наличию build.gradle / pom.xml>
Изменённые Java-файлы (без тестов): <список>

Шаги:
1. Gradle: `./gradlew test jacocoTestReport`. Maven: `mvn -q test jacoco:report`.
2. Открой XML JaCoCo
   (gradle: `build/reports/jacoco/test/jacocoTestReport.xml`,
    maven:  `target/site/jacoco/jacoco.xml`).
3. Для каждого изменённого Java-файла посчитай line coverage.

Верни ровно такой JSON (без обёрток):
{
  "tests": {
    "passed": <int>, "failed": <int>, "skipped": <int>,
    "failed_tests": [{"name": "...", "message": "..."}]
  },
  "coverage": [
    {"file": "src/main/java/...", "covered_lines": N, "missed_lines": M, "percent": 0.83}
  ],
  "below_threshold": ["src/main/java/..."],
  "missing_in_report": ["..."]
}

Ничего не чини. Если compile error до тестов — верни {"build_error": "..."}.
```

Лимит итераций «тестописатель ↔ тестраннер»: **3**. На третьей итерации не зелёное —
стоп с показом пользователю.

---

## 8. Pre-commit (опять тестраннер)

После зелёных тестов раздела 7 — полный прогон.

```
description: "Full pre-commit build for <JIRA-KEY>"
subagent_type: general-purpose

prompt:
Запусти полный pre-commit прогон. Корень проекта: <toplevel>.

Шаги (остановись на первой ошибке):
1. `./gradlew clean build -x test` или `mvn -q clean compile`
2. `./gradlew test` или `mvn -q test`
3. Линтеры, если есть:
   - spotless: `./gradlew spotlessCheck` (на падении — ОТЧИТАЙСЯ, не запускай apply)
   - checkstyle: `./gradlew checkstyleMain`
4. JaCoCo: `./gradlew jacocoTestReport`, изменённые файлы ≥ 80%.

Верни JSON:
{
  "build": "ok" | {"error": "..."},
  "tests": "ok" | {"failed": N, "details": "..."},
  "lint": {"spotless": "ok|fail|n/a", "checkstyle": "ok|fail|n/a"},
  "coverage_ok": true|false
}
```

Если spotless падает на форматировании — предложи пользователю явно
`./gradlew spotlessApply`. Не запускай молча.

---

## 9. Спецификация — спецадаптер

Зови **в самом конце, после pre-commit, до коммита кода**. Цель: создать ветку
`feature/<JIRA-KEY>` в репо спеки и внести точечные правки в .md, отражающие фикс.

```
description: "Update spec for <JIRA-KEY>"
subagent_type: general-purpose

prompt:
Главный агент только что починил минорный дефект в репозитории кода. Тесты и сборка
зелёные. Твоя задача — обновить спецификацию в ОТДЕЛЬНОМ git-репо.

Контекст:
- Ключ задачи: <JIRA-KEY>
- Корень репо спеки: <docs_path>     ← в этом репо ты работаешь, не в коде
- Корень репо кода: <git toplevel>   ← только для чтения diff'а

Diff фикса (только production-файлы, без тестов):
<git -C <toplevel> diff origin/main HEAD -- ':!**/test/**' ':!*Test.java'>

Краткая суть фикса (от главного агента):
<2-3 предложения, что и почему>

Кандидаты-разделы спеки, которые могут быть затронуты (из отчёта аналитика):
<список .md, если был>

Алгоритм:
1. Перейди в <docs_path>. Все git-команды ниже — относительно этого пути.
2. Проверь, есть ли уже ветка `feature/<JIRA-KEY>` (предыдущая попытка):
   - Есть → переключись (`git checkout feature/<JIRA-KEY>`).
   - Нет → создай от default-ветки (`git fetch && git checkout -b feature/<JIRA-KEY> origin/<default>`).
     Default-ветку определи по `git symbolic-ref refs/remotes/origin/HEAD` или возьми
     `main`/`master`/`develop` по факту наличия.
3. Найди разделы .md, описывающие изменённое поведение. Грепай по именам
   классов/методов из diff'а, по терминам домена. НЕ читай всю спеку — иди прицельно.
4. Внеси точечные правки. Принципы:
   - Меняй только то, что реально изменилось в коде. Не "улучшай по пути".
   - Сохраняй стиль документа: заголовки, форматирование, тон, нумерацию.
   - Если описанного раздела нет — НЕ выдумывай новый. Зафиксируй в отчёте, что
     "в текущей спеке этой части нет".
5. Если правок не требуется (фикс затрагивает только внутреннюю реализацию,
   неописанную в спеке) — НЕ создавай коммит. Если ветка уже создавалась — оставь её
   пустой (без коммита поверх default-ветки). Верни "no_changes": true.
6. Если правки есть — сделай ОДИН коммит со стилем коммитов спец-репо
   (`cd <docs_path> && git log -20 --pretty=format:'%s'`). Используй тот же ключ Jira
   в сообщении, если так принято в спец-репо.
7. НЕ пушь ничего. Push и PR решает пользователь.

Верни ровно такой JSON:
{
  "no_changes": false,
  "branch": "feature/STOR-1234",
  "commit_sha": "abc1234",
  "default_branch": "main",
  "files_changed": ["api/storage.md", "domain/users.md"],
  "summary": "Дополнили раздел про обработку null email в getByEmail.",
  "uncovered_in_spec": []   // фрагменты фикса, которым не нашлось места в спеке
}

Если no_changes=true — branch/commit_sha/files_changed пустые, остальное опционально.
```

### После ответа спецадаптера

**Если `no_changes: true`:**
- Сообщи пользователю одной строкой: "В спеке нет раздела про эту часть — править
  нечего."
- Запомни: spec_status = "no_changes". Перейди к разделу 10.

**Если правки есть:**
1. Покажи пользователю diff спеки:
   ```bash
   cd <docs_path> && git show <commit_sha>
   ```
2. Спроси:
   > "Что делаем со спекой?
   >  — push + PR (полный цикл)
   >  — только push (без PR)
   >  — оставить локально
   >  — откатить (удалить ветку)"
3. По ответу:
   - **push + PR** → `git push -u origin feature/<JIRA-KEY>` в `<docs_path>`, затем
     через Bitbucket MCP создай PR в spec-репо (target — default branch из ответа
     субагента). Запомни PR URL. spec_status = "pr".
   - **только push** → только push, запомни URL ветки в Bitbucket. spec_status = "branch".
   - **оставить локально** → ничего не делай. spec_status = "local".
   - **откатить** → `cd <docs_path> && git checkout <default_branch> && git branch -D feature/<JIRA-KEY>`. spec_status = "reverted".

См. `references/bitbucket-workflow.md` для определения workspace/repo в спец-репо.

---

## 10. Коммит кода

Спроси: **"Коммитим изменения кода?"**. Если "нет" — оставь рабочую копию как есть и
сообщи, что цикл остановлен.

Если "да":

### 10.1. Определи стиль коммитов проекта
```bash
git log -30 --pretty=format:'%s'
```
Распознай паттерн (Conventional Commits, префикс с ключом задачи, свободная форма,
русский/английский, регистр). При разнобое — спроси у пользователя.

### 10.2. Сформируй сообщение
- Соответствует определённому стилю.
- Описывает **почему**, не «что» (это видно в дифе).
- Содержит ключ Jira, если так у большинства прошлых коммитов.
- **Без** `Co-Authored-By: Claude`.

Покажи сообщение, спроси: "Коммитим с этим сообщением? (да / правки)".

### 10.3. Коммит
- `git add` — только нужные файлы. Без артефактов, IDE-файлов.
- Без `--amend`, `--no-verify`.
- На падении pre-commit hook — почини причину и сделай **новый** коммит.

---

## 11. PR кода

После коммита спроси: **"Создать pull request кода в Bitbucket?"** (да / нет).

Если "да":
1. `git push -u origin <branch>`.
2. Через Bitbucket MCP создай PR:
   - **title**: первая строка коммита.
   - **description**: тот же текст, что пойдёт в Jira-отчёт (раздел 12), плюс прямая
     ссылка на Jira-задачу первой строкой.
   - **target branch**: ветка, от которой ответвлена текущая.
3. Запомни PR URL. code_status = "pr".

Если "нет" — code_status = "commit_only" (есть коммит, но без push). Если ветка не
запушена — code_status = "local".

См. `references/bitbucket-workflow.md`.

---

## 12. Финальный отчёт в Jira

Теперь у тебя есть все ссылки (код и спека). Подготовь **черновик** комментария на
русском в Markdown.

```
**Что сделано:** одно-два предложения, что починено и почему.

**Изменённые файлы (код):**
- `path/to/File1.java` — короткая суть правки
- `path/to/File2.java` — короткая суть правки

**Тесты:**
- Обновлены: `FooBarTest#shouldFailWhenX`
- Добавлены: `BazTest#shouldHandleEmptyInput`
- Покрытие изменённых файлов: 87% (порог 80% выполнен)

**Код:**
- Ветка: `feature/STOR-1234`
- PR: <url> либо "коммит без push" либо "локально, без коммита"
- Коммит: <short sha>

**Спецификация:**
- зависит от spec_status (см. ниже)
```

Формат блока **Спецификация** по `spec_status`:

| spec_status | Текст |
|---|---|
| `pr` | "PR в спец-репо: <url>" |
| `branch` | "Ветка в спец-репо: <url или имя ветки>" |
| `local` | "Локальная ветка `feature/<JIRA-KEY>` в `<docs_path>`, не запушена" |
| `reverted` | "Правки спеки откачены по решению автора" |
| `no_changes` | "Правки спеки не требуются (затронутая часть не описана в спеке)" |

Покажи черновик пользователю **полностью** и спроси:
> "Отправить этот текст комментарием в Jira? (да / отредактировать / не отправлять)"

Отправляй только после явного "да". Если пользователь правит — учти и покажи новую
версию.

См. `references/jira-workflow.md`.

---

## Карта инструментов MCP

| Действие | Что искать в доступных инструментах |
|---|---|
| Получить Jira issue | `*jira*get*issue*`, `*atlassian*issue*` |
| Добавить комментарий | `*jira*add*comment*`, `*atlassian*comment*` |
| Создать PR | `*bitbucket*create*pull*request*`, `*bb*pr*create*` |
| Получить инфу о репозитории | `*bitbucket*get*repo*` |

Точные имена зависят от конкретного MCP-сервера. **Не угадывай** — проверь список
доступных инструментов и используй первый подходящий. Для spec-репо те же инструменты
Bitbucket, просто другой workspace/repo_slug.

---

## Что НЕ делать

- Не запускай задачу "тихо" — каждый необратимый шаг (комментарий в Jira, коммит,
  push, PR в код-репо, push/PR в спец-репо) требует подтверждения.
- Не используй `git push --force`, `git reset --hard`, `git checkout .` для того,
  чтобы обойти проблему. Разбирайся с причиной.
- Не добавляй "на всякий случай" логирование, проверки, try/catch.
- Не предлагай рефакторить рядом лежащий код, даже если он "просится".
- Не пытайся брать следующую задачу после закрытия текущей без отдельной просьбы.
- **Не передавай субагентам всю историю разговора** — только нужный для шага контекст.
- Не работай со спекой в репо кода и наоборот — спецадаптер всегда оперирует в
  `<docs_path>`, всё остальное — в корне кода.

---

## Ссылки

- `references/jira-workflow.md` — общение с Jira через MCP.
- `references/bitbucket-workflow.md` — создание PR через Bitbucket MCP (код и спека).
- `references/coverage.md` — парсинг JaCoCo XML и поиск непокрытых строк.
