102 lines
10 KiB
Markdown
102 lines
10 KiB
Markdown
# Архитектура Orchestrator
|
||
|
||
## Обзор
|
||
Мульти-агентный оркестратор разработки. Принимает webhooks от Plane (управление задачами) и Gitea (git-события), ведёт задачи по конвейеру стадий через Quality Gates, на каждой стадии запускает Claude CLI агента. Поддерживает несколько проектов (multi-repo) и self-hosting (дорабатывает сам себя).
|
||
|
||
## Компоненты
|
||
- **Webhook Receivers** (`src/webhooks/plane.py`, `gitea.py`) — приём событий, HMAC-проверка, дедупликация (`_dedup.py`). Роуты: `POST /webhook/plane`, `POST /webhook/gitea`.
|
||
- **State Machine** (`src/stages.py`) — `STAGE_TRANSITIONS`: переходы, агент и QG каждой стадии. Хелперы: `get_next_stage`, `get_agent_for_stage`, `get_qg_for_stage`, `get_previous_stage`.
|
||
- **Stage Engine** (`src/stage_engine.py`) — исполнение переходов, диспетчеризация QG (`_run_qg`), откаты, синхронизация с Plane.
|
||
- **Review/Test Parsers** (`src/review_parse.py`, ORCH-046) — defensive-извлечение дословного must-fix текста из артефактов для встраивания в `task_desc` заворота: `extract_review_findings` (P0/P1 из `12-review.md`), `extract_test_failures` (фрагмент тела `13-test-report.md`). Контракт «never raise»: любая ошибка → `""`.
|
||
- **Quality Gates** (`src/qg/checks.py`) — проверки выхода со стадии, реестр `QG_CHECKS`.
|
||
- **Agent Launcher** (`src/agents/launcher.py`) — запуск Claude CLI агентов в изолированном git worktree, мониторинг, auto-advance. **Валидация результата (ORCH-044):** `exit_code==0` считается успехом только если run-лог непустой и содержит валидный result-JSON; пустой/невалидный результат ⇒ job `failed`/retry + алерт, без авто-advance и «успешного» коммента.
|
||
- **Preflight** (`src/preflight.py`, ORCH-1/ORCH-044) — дешёвый token-free гейт клейма: `os.path.exists(bin)` + `claude --version` + **проверка авторизации** (чтение `<AGENT_HOME>/.claude/.credentials.json` и валидности `claudeAiOauth.expiresAt`; постфактум-маркер `Not logged in`). Кешируется на `preflight_cache_ttl`. Подробнее: [ADR work-item ORCH-044](../work-items/ORCH-044/06-adr/ADR-001-preflight-auth-and-empty-result-failure.md).
|
||
- **Queue** (`src/queue_worker.py`, ORCH-1) — персистентная очередь задач (SQLite `jobs`), atomic claim, max_concurrency, ретраи, restart-safe. Не клеймит job при `preflight=fail` (в т.ч. auth-fail).
|
||
- **Project Registry** (`src/projects.py`, ORCH-6) — Plane project id → repo + prefix; фильтрация вебхуков по проекту.
|
||
- **Plane Sync** (`src/plane_sync.py`) — синхронизация статусов/комментариев в Plane.
|
||
|
||
## Конвейер и Quality Gates
|
||
|
||
```
|
||
created → analysis → architecture → development → review → testing → deploy-staging → deploy → done
|
||
↑ │
|
||
└──── REQUEST_CHANGES ──────┘ (откат на development, max 3 retries)
|
||
```
|
||
|
||
| Стадия | Агент (выход) | Quality Gate | Артефакт |
|
||
|--------|---------------|--------------|----------|
|
||
| created | analyst | — | — |
|
||
| analysis | architect | `check_analysis_approved` | 01-brd / 02-trz / 03-acceptance-criteria / 04-test-plan.yaml |
|
||
| architecture | developer | `check_architecture_done` | 06-adr/ |
|
||
| development | reviewer | `check_ci_green` | код + PR |
|
||
| review | tester | `check_reviewer_verdict` | 12-review.md (`verdict:`) |
|
||
| testing | deployer | `check_tests_passed` | 13-test-report.md |
|
||
| deploy-staging | deployer | `check_staging_status` | 15-staging-log.md (`staging_status:`) |
|
||
| deploy | — | `check_deploy_status` | 14-deploy-log.md (`deploy_status:`) |
|
||
| done | — | — | — |
|
||
|
||
**Реестр QG** (`QG_CHECKS`): check_analysis_approved, check_analysis_complete, check_architecture_done, check_ci_green, check_review_approved, check_tests_passed, check_reviewer_verdict, check_tests_local, check_deploy_status, check_staging_status.
|
||
|
||
**Канон гейтов:** машинные вердикты читаются ТОЛЬКО из YAML-frontmatter, никогда из прозы. Лог-файлы мержатся в `origin/main` отдельным PR; гейт читает из `origin/main`.
|
||
|
||
### Условный staging-гейт (ORCH-35)
|
||
`check_staging_status` реален только для self-hosting (`is_self_hosting_repo(repo)` → `orchestrator`); для остальных проектов → no-op `(True, "Staging gate N/A")`. Для orchestrator парсит `staging_status:` из `15-staging-log.md`; FAILED → откат на `development`. Подробнее: [ADR-0003](adr/adr-0003-staging-gate.md).
|
||
|
||
## Откаты
|
||
- Reviewer REQUEST_CHANGES → откат на `development` + retry (`MAX_DEVELOPER_RETRIES = 3`).
|
||
- Tester `check_tests_passed` FAIL → откат на `development` + retry.
|
||
- Deploy / deploy-staging FAILED → откат на `development`.
|
||
- `get_previous_stage` использует порядок ключей `STAGE_TRANSITIONS`.
|
||
|
||
### Обогащение `task_desc` при заворотах (ORCH-046)
|
||
При откате на `development` `task_desc` (попадает в `.task-dev.md` developer-агента) несёт **дословный must-fix текст**, а не только ссылку — чтобы агент видел суть претензий сразу и не повторял ту же ошибку:
|
||
- **reviewer REQUEST_CHANGES** → дословные пункты P0/P1 из секции `## Findings` файла `12-review.md` (`extract_review_findings`);
|
||
- **tester `check_tests_passed` FAIL** → `reason` гейта + фрагмент тела `13-test-report.md` (приоритет: `## Вывод pytest` → FAIL-строки `## Результаты` → `## Итог`; `extract_test_failures`).
|
||
|
||
Ссылка на полный файл-артефакт сохраняется всегда («Полный контекст»). Парсеры `src/review_parse.py` — defensive (never-raise); при отсутствующем/битом артефакте `task_desc` graceful-фоллбэк на прежнюю ссылку-строку, последовательность отката и retry-счётчик не меняются (ADR `docs/work-items/ORCH-046/06-adr/ADR-001-embed-findings-in-task-desc.md`).
|
||
|
||
### Plane Sync: единый status-коммент агентов (ORCH-016)
|
||
Все агенты (analyst / architect / developer / reviewer / tester / deployer) пишут финальный коммент через **один хелпер** `usage.build_status_comment(...)` (ADR `docs/work-items/ORCH-016/06-adr/ADR-001-unified-status-comment.md`). Формат HTML, разделители `<br>`:
|
||
|
||
```
|
||
{ICON} {RoleName} — {описание стадии}
|
||
[Verdict|Status: VALUE] # reviewer/tester/deployer, из YAML-frontmatter артефакта
|
||
[Длительность: 4m 12s] # явный duration_s от launcher, либо fallback из agent_runs
|
||
<b>Документы:</b><ul><li><a href="…">label</a></li>…</ul>
|
||
[<sub>8.5M in / 45.8k out · $7.29</sub>] # тех-хвост usage; опускается при нулях
|
||
```
|
||
|
||
- **Длительность** считается launcher'ом (`_monitor_agent`) и пробрасывается в `_post_usage_comments`; для analyst (коммент строится в `stage_engine`) используется DB-фоллбэк `usage.get_agent_duration(task_id, agent)`.
|
||
- **Vердикт-парсер** — `src/frontmatter.read_frontmatter_value(...)` (defensive, никогда не raise). Машинные ключи: reviewer → `verdict:` (12-review.md); **testing-гейт `check_tests_passed` (13-test-report.md) → любое из трёх равноправных: `result:` (канон промпта тестера), `verdict:`, `status:`** (ORCH-047, ADR-001); deployer → `deploy_status:` (14-deploy-log.md), `staging_status:` (15-staging-log.md). Negative-токен в любом поле авторитетен (перебивает positive).
|
||
- Формат коммента **не** меняет реестр гейтов и стадий; коммент — отображение, не управление.
|
||
|
||
## База данных (SQLite)
|
||
- `events` — входящие вебхуки (дедуп)
|
||
- `tasks` — задачи и их стадии
|
||
- `agent_runs` — запуски агентов (run_id, usage, cost)
|
||
- `jobs` — очередь задач (ORCH-1)
|
||
|
||
## Изоляция (git worktree, ORCH-2)
|
||
Каждая задача исполняется в отдельном git worktree, ветки не пересекаются. Репозитории проектов разделены под `/repos/<project>`.
|
||
|
||
## API
|
||
| Method | Path | Описание |
|
||
|--------|------|----------|
|
||
| GET | `/health` | health check |
|
||
| GET | `/status` | активные задачи (stage != done) |
|
||
| GET | `/queue` | очередь: counts + max_concurrency + последние jobs |
|
||
| POST | `/webhook/plane` | Plane webhook |
|
||
| POST | `/webhook/gitea` | Gitea webhook (push, PR, CI status) |
|
||
|
||
## Деплой и эксплуатация
|
||
Топология, контейнеры, порты, env-карта, self-hosting риски — [docs/operations/INFRA.md](../operations/INFRA.md). Деплой-хук — [DEPLOY_HOOK.md](../operations/DEPLOY_HOOK.md). Staging — [STAGING.md](../operations/STAGING.md).
|
||
|
||
## ADR
|
||
Сквозные архитектурные решения — [adr/](adr/). Per-work-item решения — `docs/work-items/<id>/06-adr/`.
|
||
|
||
## Детали реализации
|
||
Схема БД, потоки данных, resilience-слой, детали Dockerfile — [internals.md](internals.md).
|
||
|
||
---
|
||
*Актуально на 2026-06-05 (main `f1b3146`). Обновлять при изменении src/stages.py, src/qg/checks.py, src/main.py.*
|