Files
EvoBGP/.cursor/rules/conventional-commits.mdc
Denozordec 4db6438245
CI / openapi (push) Has been cancelled
CI / web (push) Has been cancelled
CI / changes (push) Has been cancelled
CI / go (push) Has been cancelled
CI / bird2 (push) Has been cancelled
CI / commitlint (push) Has been cancelled
CI / release (push) Has been cancelled
remove commitlint configuration and update release documentation to enforce single scope in commit messages
2026-05-21 17:54:41 +07:00

181 lines
9.1 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: >-
Conventional Commits EvoBGP. Триггеры commit/коммит/закоммить/staged/commit message —
ОБЯЗАТЕЛЬНО сначала Shell scripts/commit/staged-context.ps1, скилл commit-message.
alwaysApply: false
---
# Conventional Commits (EvoBGP)
Полное описание релизного пайплайна: [docs/releasing.md](../../docs/releasing.md).
## Триггеры (применить правило + скилл)
Любой запрос на коммит или сообщение коммита: `commit`, `коммит`, `закоммить`, `git commit`, `commit message`, `conventional commit`, `staged`, «сгенерируй коммит», **`/commit-message`** — в т.ч. если это указано в плане или [AGENTS.md](../../AGENTS.md).
### Не путать с кнопкой ✨ в Source Control
Команда **`cursor.generateGitCommitMessage`** (sparkle в поле commit message) **не** читает Rules, Skills и `staged-context.ps1` — только staged diff и история коммитов ([ограничение Cursor](https://forum.cursor.com/t/how-to-set-prompt-for-generate-commit-message/148606)).
**Замена для EvoBGP:** Agent → `/commit-message` или команда [`.cursor/commands/commit-message.md`](../commands/commit-message.md).
## Обязательный запуск скрипта (MUST)
1. Прочитать скилл [`.cursor/skills/commit-message/SKILL.md`](../skills/commit-message/SKILL.md).
2. **Первым действием** выполнить Shell (из корня репо):
```powershell
powershell -NoProfile -File scripts/commit/staged-context.ps1
```
3. Сообщение коммита строить **только** по JSON из stdout скрипта (`groups`, `diff_excerpt`, `stat`).
4. **Запрещено** генерировать commit message без успешного (exit 0) запуска скрипта; не заменять скрипт одним `git diff --cached`.
## Формат (строго)
```
<type>(<scope>): <short summary in English>
<тело на русском: что изменено и зачем>
```
- **Заголовок** — только английский; императив, без точки в конце; ≤72 символов.
- **Тело** — только русский; полные предложения; пустая строка после заголовка.
- Запрещены vague-сообщения: `fix bug`, `update code`, `wip`, `misc`.
## Типы (semantic-release)
| type | Когда | Версия |
|------|--------|--------|
| `feat` | **новая** пользовательская возможность (раньше нельзя было) | minor |
| `fix` | восстановление **ожидаемого** поведения; баг, регрессия, падение UI | patch |
| `perf` | ускорение без смены API | patch |
| `refactor` | реструктуризация **без** новой возможности и **без** исправления бага | patch |
| `docs` | только документация | — |
| `test` | тесты | — |
| `ci` | CI/CD (`.gitea/`, workflows); правки, из‑за которых нужны новые образы | patch |
| `chore` | обслуживание, deps, `.cursor/` | — |
### Выбор type: semver, а не «красивые слова»
**Главный вопрос:** что изменится для пользователя после релиза?
1. Появилось **новое** действие / экран / API / настройка, которых не было → `feat`
2. То, что **должно было работать**, не работало (кнопки, диалоги, сохранение, 500) → `fix`
3. Только перестройка кода или UI на другой паттерн, поведение для пользователя то же → `refactor` (patch, без новых функций)
4. Ускорение без изменения контракта → `perf`
**Не путать с формулировкой diff:**
| В diff / задаче часто пишут | Неверный type | Верный type, если… |
|-----------------------------|---------------|---------------------|
| enhance, improve, polish UI | `feat` | …только чиним сломанное после прошлого PR → `fix` |
| refactor pages, unify tables | `feat` | …новой возможности нет, лишь перенос на AppDataTable → `refactor` |
| follow-up после feat(web) | `feat` | …исправляем баги того же экрана → `fix` |
**Follow-up rule:** коммит сразу после `feat` в той же области, который **не добавляет** новую возможность, а устраняет дефект (effect loop, не открывается dialog, confirm не срабатывает) — **`fix`**, не `feat`.
**Split при смешанном diff:** новая страница/flow → `feat`; отдельным коммитом правки багов → `fix`. Не объединять в один `feat`.
**Breaking changes** — только `feat!` / `fix!` / `BREAKING CHANGE:` когда пользователь **обязан** менять конфиг, API или привычный workflow.
### Обязательно в пояснении агенту
При каждом предложении коммита указать:
- **Semver impact:** `minor` | `patch` | `none` | `major`
- **Почему не другой type** (одно предложение), если diff большой или формулировка двусмысленная
Пример неправильно / правильно:
```
# Плохо — patch-фикс, minor-bump
feat(web): enhance module entry dialogs and selection handling
# Хорошо
fix(web): stop effect loop breaking module action buttons
Исправлен effect_update_depth_exceeded и bind:open у Dialog; кнопки редактирования/удаления снова работают.
```
```
# Плохо — рефакторинг без новой фичи
feat(web): migrate modules list to AppDataTable
# Хорошо — если не было нового user-facing
refactor(web): migrate modules list to AppDataTable
Единый паттерн таблиц; поведение списка модулей без изменений. Semver: patch.
```
```
# Хорошо feat — действительно новое
feat(web): add module create dialog on /modules
Диалог создания модуля с POST /v1/modules; раньше создание было только через API.
```
## Breaking changes
- Заголовок: `feat!` / `fix!` **или** в теле строка `BREAKING CHANGE:` (на английском ключевое слово) + описание impact **на русском**.
## Scope (EvoBGP)
Выбирать по доминирующему пути из staged diff:
| Префикс | scope |
|---------|-------|
| `internal/httpapi/` | `httpapi` |
| `internal/store/`, `internal/repository/`, `internal/db/` | `store` |
| `internal/jobs/` | `jobs` |
| `internal/pipeline/` | `pipeline` |
| `internal/birdfmt/` | `birdfmt` |
| `internal/birddeploy/` | `birddeploy` |
| `internal/bundle/`, `internal/signing/` | `bundle` |
| `cmd/` | `cmd` |
| `web/` | `web` |
| `docs/openapi.yaml`, `redocly.yaml` | `openapi` |
| `docs/` (остальное) | `docs` |
| `migrations/` | `db` |
| `.gitea/` | `ci` |
| `deploy/` | `deploy` |
| `.cursor/` | `chore` |
| прочее в корне | `chore` |
**Запрещено:** несколько scope через запятую (`refactor(web, httpapi): …`) — semantic-release не распознает `type`, релиз не будет (см. [docs/releasing.md](../../docs/releasing.md)).
`type` определять по **содержимому diff**, не только по пути.
## Multi-change
- Несвязанные области → **отдельные коммиты** (auto-split по скиллу).
- Одна логическая фича через несколько scope (OpenAPI + httpapi + web) → **один** коммит, scope по главной области.
## Обязательный вывод агенту
Для каждого коммита:
**1. Готовое сообщение** (копировать в `git commit -m` / HEREDOC):
```
<type>(<scope>): <summary>
<тело RU>
```
**2. Пояснение (RU):** semver impact (`minor`|`patch`|`none`|`major`); почему выбран type; риск/impact; был ли split.
## Примеры
```
feat(httpapi): add version endpoint and wire web footer
Добавлен GET /v1/version. В Web UI версия в footer берётся из API вместо захардкоженного значения.
```
```
fix(auth): correct token validation edge case
Исправлена ложная 401 при истёкшем refresh-токене с валидной сессией.
```