Files
main/.ai/conventions/engineering-workflow.md
T

172 lines
18 KiB
Markdown
Raw 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.
# Engineering Workflow
Область: пять независимых checkout workspace (`main`, `frontend`, `backend`,
`docs`, `specs`). Репозиторий `deploy` существует в Gitea отдельно и применяет
свои локальные правила. Этот документ — единственный владелец общего процесса;
локальные AGENTS и conventions определяют технические проверки и ограничения.
## Issue Management
| Переход | Условие входа → действие → условие выхода |
| --- | --- |
| Request → Issue | До изменения файлов/конфигурации/спецификаций определить затронутые repos, найти по смыслу открытые и закрытые Issues, проверить актуальность и scope. Взять подходящую открытую Issue (закрытую переоткрыть только для действительно незавершённой работы) либо создать одну новую. Чтение, анализ и предложение изменений разрешены без Issue. |
| Issue → Analysis | В Issue должны быть результат в title, контекст/проблема и ожидаемое поведение, проверяемые Acceptance Criteria. Уточнить неизвестное до зависимого решения. Выбрать тип и приоритет; назначить исполнителя, если известен; milestone только при реальном плане, dependencies/related Issues только при наличии. |
| Analysis → Delivery | Определить область и риски, выбрать lightweight или SDD ниже. Если AC или owner меняются, сначала обновить соответствующую Issue/согласование. |
Типы: `feature`, `bug`, `refactor`, `tech-debt`, `docs`, `test`, `ci`,
`chore`, `performance`. Существующие org labels отражают их без требования
один-к-одному: `Kind/Feature`, `Kind/Bug`, `Kind/Refactor`,
`Kind/Documentation`, `Kind/Testing`, `Kind/Enhancement` (performance);
repo-local `Kind/Process` подходит для ci, chore и process/tech-debt.
Дополнительные `Kind/Security`, `Kind/Investigation`, `Kind/Dependencies`
(последние два — repo-local) — по ситуации. Priority: существующие
`Priority/Critical|High|Medium|Low`.
Gitea assignee, milestone и state не дублируются labels. Для назначаемых
Issue и PR выбирай `hermes-agent`; незанятую задачу не назначай формально.
Шаблоны ускоряют ввод, но не доказывают качество заполнения.
Один координирующий Issue достаточен, если результат и AC едины, одна команда
может принять работу целиком и отдельные repos не требуют независимой поставки.
Иначе Issue в каждом независимо принимаемом repo; ссылаться друг на друга и
указать порядок зависимостей. Номера `#27` локальны: для чужого repo использовать
`WealthLedger/main#27` или полный URL. Не заводить дубль только из-за второго PR.
## Git Branching
| Переход | Условие входа → действие → условие выхода |
| --- | --- |
| Analysis → Branch | Issue и AC определены; проверить `git status`, текущую ветку и `origin/develop`. Использовать существующую подходящую ветку либо создать одну от актуального `develop` каждого affected repo. Чужие изменения не переносить. |
| Branch → Implementation | `<type>/<issue-number>-<english-kebab-description>`; номер принадлежит указанной в PR Issue (для cross-repo — координатору). Примеры: `feature/123-import-transactions`, `fix/124-invalid-balance`, `refactor/125-simplify-api-client`, `docs/126-update-architecture`. |
Префиксы: feature → `feature`, bug → `fix`, refactor/tech-debt →
`refactor`, docs → `docs`, test → `test`, ci → `ci`, chore → `chore`,
performance → `perf`. Номер обязателен для новых рабочих веток; короткий
английский slug в kebab-case. Ветки `main`/`develop` не место для прямой
разработки. Release, Renovate и исторические ветки подчиняются существующему
release/automation процессу, а не переименовываются.
Рабочий PR сливается squash или rebase-merge; merge-коммит не используется.
`main` обновляется только fast-forward из `develop`, поэтому `origin/main`
всегда предок `origin/develop`. Срочный fix — обычная ветка `fix/*` от
`develop`; отдельного hotfix-пути от `main` в обычном процессе нет.
Merge policy, версии, теги и исключения принадлежат
[процессу релиза](../../README.md#релизы-и-ветки).
## Commit Conventions
| Переход | Условие входа → действие → условие выхода |
| --- | --- |
| Implementation → Commit | Одна связанная задача на commit, проверить staged paths/diff. Заголовок Conventional Commits с осмысленным subject и ссылкой на Issue: `feat(portfolio): add transaction import (#123)` или `ci: align gates (WealthLedger/main#27)`. Scope только при полезной области. |
Commitlint требует распознаваемую conventional-commits-parser ссылку, но не
проверяет числовой формат, существование Issue, её смысл или корректный repo.
Использовать `#N` только для локальной Issue и `WealthLedger/repo#N` для чужой;
это формат команды, проверяемый при review. Не добавлять custom validator
ради более строгой регулярной проверки. Без `fixes`,
`closes`, `resolves` в сообщении: не закрывать задачу первым коммитом.
Ссылка в footer тоже принимается commitlint; размещение в заголовке остаётся
правилом команды. Если заголовок PR после squash станет commit title, оставить
в нём ссылку. `chore(release): X.Y.Z` освобождён только при точном SemVer
заголовке release-it. Стандартные Gitea merge commits освобождаются по точному
шаблону merge message; sync PR используют обычный review/merge process.
Шаблонные сообщения `Revert`/`fixup!`/`squash!` не освобождаются: revert
оформляй как `revert: … (#N)`. Историю не переписывать ради формата.
## Pull Request Process
| Переход | Условие входа → действие → условие выхода |
| --- | --- |
| Validation → PR | Завершить AC и релевантные локальные проверки; PR в `develop` из рабочей ветки, только связанный diff. В теле: Summary, Linked Issue, Changes, Verification (команда/результат/ограничения), Breaking Changes при наличии. Для cross-repo PR указывать полный reference и связанные PR. |
| PR → Review → Merge | Дождаться required checks на финальной ревизии, проверить AC, значимые изменения — review владельца/специалиста. При замечаниях исправить и обновить evidence. Merge только по политике repo. |
| Merge → Issue Closed | Закрыть Issue после принятия **всех** связанных delivery areas, документации и при SDD — обязательной verification/archive; multi-PR Issue остаётся открытой до последнего результата. |
Перед передачей PR на review перенеси в него тип и приоритет связанной Issue,
назначь `hermes-agent`, привяжи к подходящему milestone (если он есть) и к
`WealthLedger — Delivery Board`, колонка «На проверке». Для cross-repo PR
используй milestone его собственного repo. Колонку меняй вместе со стадией:
при блокировке — «Заблокировано», после принятия — «Готово». Не вводи label
этапа вместо встроенной колонки проекта.
Для SDD отдельные pre-archive checks/semantic review выполняются до archive по
локальной schema; порядок merge/archive согласуется с конкретным change, но
Issue закрывается только после обоих событий. Не подменять OpenSpec approval
обычным PR review.
## SDD Integration
Lightweight: локальный bugfix с известным ожидаемым поведением, docs-only,
рефакторинг без изменения контрактов/наблюдаемого поведения и малые CI-правки:
`Issue → Analysis → Branch → Implementation → Validation → PR`.
SDD: новая функциональность, изменение публичного API, бизнес-правил, поведения
нескольких компонентов, архитектуры или неоднозначные требования. После Issue
уточнить намерение и запросить согласование Change Owner на вход в OpenSpec;
OpenSpec lifecycle применяется только по явному запросу/решению владельца.
Использовать **только** store `wealth-ledger-specs` и его локальный lifecycle:
Proposal → Delta Specs → System Analysis → Design + QA Analysis → Docs Impact →
Tasks → Apply (для legacy change — его собственная schema). Явные approvals
перед downstream artifacts и Apply не заменяются Issue/PR. Ветка specs может
появиться для planning; ветки реализации — когда Apply разрешён, без
насильственной общей точки создания всех веток. Связать Issue ↔ change ID ↔
PR текстовыми ссылками; после проверки применить штатные sync/archive и
completion evidence согласно локальной schema. Число файлов не определяет SDD.
Если владелец не согласовал вход в SDD, не начинать зависящую реализацию
контракта/семантики и явно сообщить блокировку.
## AI Agent Responsibilities
Перед edit — поиск подходящей Issue, AC, workflow, branch/status каждого repo;
затем только согласованный scope. По завершении — итоговый diff, проверенные
команды и ограничения, подготовка commit/PR по запросу и статус Issue. Чтение
не требует Issue. Если Gitea недоступна, сообщить об этом до edit и запросить
issue reference; не выдавать локальную заметку за Issue. Агенты используют
локальные инструкции репозитория и его CI inputs, не полагаются на соседние
checkout как обязательную build-зависимость. Этот источник доступен в main;
при недоступной ссылке самостоятельный checkout сохраняет обязательный минимум
в своём AGENTS и не блокирует локальную работу из-за отсутствия root checkout.
## Quality Gates
Итерации: узкие проверки по риску; после логического изменения — релевантные
тесты; перед передачей результата — локальные обязательные gates данного repo
на итоговом diff; CI — независимые полные проверки. Не повторять дорогой verify
после каждого файла; повторить при изменении значимых входов. `main`: `commits`;
остальные: локальные `verify`, `security`, `commits` согласно фактическим CI.
Frontend/backend запускают их как jobs в едином `verify.yml`, docs/specs —
как отдельные workflows; второго CI ради одного правила не требуется.
Для Markdown-only не запускать application build. Результат lint не заменяет
семантическую проверку. Обязательность merge checks зависит от защиты ветки.
| Правило | Уровень на момент принятия документа |
| --- | --- |
| Conventional Commits и parser-recognized Issue reference в PR title/commits | CI-проверка через существующий commitlint; блокировка merge **только если** check обязателен в branch protection. Не гарантирует numeric reference, существование или соответствие Issue. Точный release SemVer title и штатные Gitea merge messages исключены. Локальные hooks не гарантируют server-side. |
| PR вместо прямого push; successful checks перед merge | Enforced только в repos/ветках, где Gitea branch protection настроена и проверена владельцем. YAML сам по себе не защищает ветку. |
| Поиск актуальной Issue, AC, корректный repo, branch name/source, соответствие ссылки, SDD selection, scope, статус | Agent-guided; templates и текст не могут гарантировать соответствие. |
| Значимое review, соответствие AC/контракту, исключения и closure после всех PR | Manual; approval может быть required в Gitea, если есть независимый reviewer. |
## Exceptions and Recovery
Срочный hotfix: немедленно завести/найти Issue, затем исправление в
обычной ветке `fix/<issue>-<slug>` от актуального `develop`, PR в `develop`
и релиз по существующему процессу. Отдельного пути от `main` нет: он сделал бы
`main` не-предком `develop`. Если `develop` содержит незаконченную работу,
быстрого фикса нет; обход требует явного решения и описан в
[процессе релиза](../../README.md#ограничения-модели). Связать Issue
в PR и сопровождающем коммите. Не отменять Issue или проверки из-за срочности.
Если CI красный или PR устарел — исправить в той же ветке и перепроверить
актуальный HEAD; если AC изменились — обновить Issue и при SDD вернуть change
к затронутому approval gate. При недоступной Gitea продолжать только анализ.
Изменение PR title после зелёного CI: проверить, что check пересчитан;
если `edited` trigger у существующих checks отсутствует, reviewer проверяет
текущий title вручную. Новые правила не применяются к историческим коммитам
и merge-коммитам, уже находящимся в истории.
Примеры: фича с новым поведением — Issue → согласованный OpenSpec change →
ветки Apply → PR каждого affected repo → archive → закрытие Issue. Локальный
bugfix — Issue → `fix/124-invalid-balance` → регрессия → PR → закрытие.
Cross-repo контракт — одна Issue с общими AC, `backend` и `frontend` PR с
`WealthLedger/main#27` и взаимными ссылками; если независимые acceptance/owners,
отдельные связанные Issues. Рефакторинг без изменения поведения — lightweight
`refactor/125-simplify-api-client`. Hotfix — Issue → `fix/*` от `develop` →
PR в `develop` → релиз → закрытие.