diff --git a/README.md b/README.md index 9700b39..91daf27 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,141 @@ # Multi-Agent Orchestrator -FastAPI-сервис для оркестрации мульти-агентного пайплайна разработки. +FastAPI-сервис для оркестрации мульти-агентного пайплайна разработки. Принимает webhooks от Plane и Gitea, управляет жизненным циклом задач через Quality Gates, запускает Claude CLI агентов на каждой стадии. -## Что делает +## Архитектура -- Принимает webhooks от **Plane** (task management) и **Gitea** (git events) -- Проверяет Quality Gates перед переходом между стадиями -- Запускает **Claude CLI** агентов (analyst, architect, developer, reviewer, tester) -- Ведёт журнал событий в SQLite +``` +Plane (task mgmt) ──webhook──┐ + ├──► Orchestrator (FastAPI) ──► Quality Gates ──► Agent Launcher +Gitea (git events) ─webhook──┘ │ │ + ▼ ▼ + SQLite DB Claude CLI + (events, tasks, (analyst, architect, + agent_runs) developer, reviewer, tester) +``` + +## Стадии пайплайна + +``` +created → analysis → architecture → development → review → testing → deploy → done + ↑ │ + └─── REQUEST_CHANGES ─┘ (max 3 retries) +``` + +| Стадия | Агент | Quality Gate (выход) | Триггер перехода | +|--------|-------|---------------------|------------------| +| created | — | — | Plane webhook (work_item.created) | +| analysis | analyst | Файлы BRD/TRZ/AC/TestPlan | Push docs/ | +| architecture | architect | ADR или infra-requirements | Push docs/ | +| development | developer | CI green | Gitea status event | +| review | reviewer | PR approved (no stale) | Gitea review event | +| testing | tester | Test report с PASS | Auto-advance после tester | +| deploy | — | — | PR merge | +| done | — | — | — | ## API Endpoints | Method | Path | Описание | |--------|------|----------| | GET | `/health` | Health check | -| GET | `/status` | Активные задачи | +| GET | `/status` | Активные задачи (stage != done) | | POST | `/webhook/plane` | Plane webhook receiver | | POST | `/webhook/gitea` | Gitea webhook receiver | -## Настройка +## Структура проекта -```bash -cp .env.example .env -# Заполнить токены в .env +``` +src/ +├── main.py # FastAPI app, lifespan (orphan recovery) +├── config.py # Pydantic settings (env vars) +├── db.py # SQLite: init, get_db, update_task_stage +├── stages.py # State machine (transitions, agents, QG) +├── notifications.py # Уведомления (логирование) +├── plane_sync.py # Синхронизация статусов с Plane API +├── agents/ +│ └── launcher.py # AgentLauncher: launch, monitor, watchdog, auto-advance +├── webhooks/ +│ ├── plane.py # Plane webhook handler +│ └── gitea.py # Gitea webhook handler (push, PR, CI status) +└── qg/ + └── checks.py # Quality Gate checks (filesystem + Gitea API) +data/ +├── orchestrator.db # SQLite database +└── runs/ # Agent output logs ({run_id}.log) +docs/ +├── ARCHITECTURE.md # Подробная архитектура +├── LESSONS_ET006.md # Lessons learned из ET-006 +├── BUGFIXES_2026-05-21.md # Багфиксы +└── SETUP_WEBHOOKS.md # Настройка webhooks +docker-compose.yml # Deployment config +Dockerfile # Python 3.12 + Docker CLI + tini ``` -## Запуск (Docker) +## Запуск + +### Docker (production) ```bash docker compose up -d --build ``` -## Запуск (dev) +### Dev ```bash pip install -r requirements.txt uvicorn src.main:app --reload --port 8500 ``` -## Тесты +## Конфигурация -```bash -pip install pytest -pytest tests/ -v -``` - -## Переменные окружения +Все переменные с префиксом `ORCH_`: | Переменная | Описание | Default | |-----------|----------|---------| | `ORCH_PLANE_API_URL` | Plane API URL | `http://localhost:8091` | | `ORCH_PLANE_API_TOKEN` | Plane API token | — | -| `ORCH_PLANE_WEBHOOK_SECRET` | Webhook secret для верификации | — | +| `ORCH_PLANE_WEBHOOK_SECRET` | Webhook secret | — | +| `ORCH_PLANE_WORKSPACE_SLUG` | Workspace slug | — | +| `ORCH_PLANE_PROJECT_ID` | Project UUID | — | | `ORCH_GITEA_URL` | Gitea URL | `http://localhost:3000` | | `ORCH_GITEA_TOKEN` | Gitea API token | — | | `ORCH_GITEA_WEBHOOK_SECRET` | Gitea webhook secret | — | -| `ORCH_CLAUDE_BIN` | Путь к Claude CLI | `/usr/bin/claude` | -| `ORCH_REPOS_DIR` | Директория с репозиториями | `/home/slin/repos` | -| `ORCH_DB_PATH` | Путь к SQLite БД | `/app/data/orchestrator.db` | +| `ORCH_GITEA_OWNER` | Gitea repo owner | `admin` | +| `ORCH_DEFAULT_REPO` | Default repository | `enduro-trails` | +| `ORCH_CLAUDE_BIN` | Путь к Claude CLI | `/opt/claude-code/bin/claude.exe` | +| `ORCH_REPOS_DIR` | Repos dir (container) | `/repos` | +| `ORCH_HOST_REPOS_DIR` | Repos dir (host) | `/home/slin/repos` | +| `ORCH_DB_PATH` | SQLite path | `/app/data/orchestrator.db` | -## Архитектура +## Ключевые механизмы +### Auto-advance +После успешного завершения агента (exit_code=0), `_try_advance_stage()` проверяет QG и автоматически продвигает задачу + запускает следующего агента. + +### Review bounce +При REQUEST_CHANGES от reviewer задача откатывается в development, developer перезапускается (до 3 попыток). При исчерпании — эскалация. + +### Orphan recovery +При старте контейнера все runs с `finished_at IS NULL` старше 35 минут помечаются как failed (exit_code=-1). + +### Watchdog +Каждый агент имеет timeout 30 минут. При превышении — SIGKILL + запись exit_code=-9. + +### Event routing +Gitea events роутятся по типу: +- `push` → проверка файлов, advance architecture/development +- `pull_request*` (wildcard) → review approved/rejected, PR merge +- `status` → CI green/failure + +## Тесты + +```bash +pytest tests/ -v ``` -Plane webhook ──┐ - ├──► Orchestrator ──► Quality Gates ──► Agent Launcher ──► Claude CLI -Gitea webhook ──┘ │ - ▼ - SQLite (events, tasks, agent_runs) -``` + +## Известные ограничения + +1. **Single-task** — одновременно обрабатывается одна задача на репозиторий (нет параллелизма) +2. **Plane sync** — маппинг issue ID может быть некорректным (P3, в работе) +3. **Tester timeout** — e2e тесты с Playwright могут занимать >25 мин на тяжёлых фичах +4. **No retry on API errors** — httpx вызовы к Gitea/Plane без retry logic diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..69e033d --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,200 @@ +# Архитектура Orchestrator + +## Обзор + +Orchestrator — event-driven FastAPI сервис, который управляет жизненным циклом задач разработки через мульти-агентный пайплайн. Каждая задача проходит через фиксированные стадии, на каждой из которых работает специализированный Claude CLI агент. + +## Компоненты + +### 1. Webhook Receivers + +#### Plane Webhook (`src/webhooks/plane.py`) +- Принимает `work_item.created` — создаёт задачу в DB, запускает analyst +- Принимает `work_item.updated` — синхронизация статусов + +#### Gitea Webhook (`src/webhooks/gitea.py`) +- **push** — проверяет наличие артефактов (docs/, src/), продвигает стадию +- **pull_request\*** (wildcard) — обрабатывает review approved/rejected, PR merge +- **status** — CI green/failure, продвигает development → review + +### 2. State Machine (`src/stages.py`) + +Линейный пайплайн с одним возможным откатом (review → development): + +``` +STAGE_TRANSITIONS = { + created: → analysis (agent: None) + analysis: → architecture (agent: architect, QG: check_analysis_complete) + architecture: → development (agent: developer, QG: check_architecture_done) + development: → review (agent: reviewer, QG: check_ci_green) + review: → testing (agent: tester, QG: check_review_approved) + testing: → deploy (agent: None, QG: check_tests_passed) + deploy: → done (agent: None, QG: None) +} +``` + +### 3. Quality Gates (`src/qg/checks.py`) + +| Check | Метод проверки | +|-------|---------------| +| check_analysis_complete | Filesystem: 4 файла в docs/work-items/{id}/ | +| check_architecture_done | Filesystem: ADR dir или infra-requirements.md | +| check_ci_green | Gitea API: GET /commits/{branch}/status | +| check_review_approved | Gitea API: GET /pulls/{n}/reviews (skip stale) | +| check_tests_passed | Filesystem: test-report.md содержит "PASS" | + +### 4. Agent Launcher (`src/agents/launcher.py`) + +Запускает Claude CLI как subprocess: + +```bash +claude.exe --print --system-prompt --allowedTools Read,Write,Edit,Bash +``` + +Каждый запуск: +1. Записывает run в DB (agent_runs) +2. Запускает subprocess с stdout → `/app/data/runs/{id}.log` +3. Стартует **watchdog thread** (timeout 30 мин → SIGKILL) +4. Стартует **monitor thread** (ждёт завершения → git commit/push → auto-advance) + +### 5. Auto-advance (`launcher._try_advance_stage`) + +После успешного завершения агента: +1. Определяет текущую стадию задачи +2. Проверяет QG для выхода из стадии +3. Если QG пройден — продвигает стадию +4. Запускает следующего агента (если определён) + +Исключение: `check_review_approved` — обрабатывается через PR webhook, не через auto-advance. + +### 6. Review Bounce + +При REQUEST_CHANGES: +1. Считает количество developer runs для задачи +2. Если < MAX_DEV_RETRIES (3) — откатывает в development, перезапускает developer +3. Если >= MAX_DEV_RETRIES — эскалация (логирование + уведомление) + +## Database Schema + +```sql +-- Задачи +CREATE TABLE tasks ( + id INTEGER PRIMARY KEY, + work_item_id TEXT, -- Plane issue identifier (e.g. "ET-006") + plane_issue_id TEXT, -- Plane UUID + repo TEXT, + branch TEXT, + stage TEXT DEFAULT 'created', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Запуски агентов +CREATE TABLE agent_runs ( + id INTEGER PRIMARY KEY, + task_id INTEGER REFERENCES tasks(id), + agent TEXT, -- analyst/architect/developer/reviewer/tester + started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + finished_at TIMESTAMP, + exit_code INTEGER, + output_path TEXT -- /app/data/runs/{id}.log +); + +-- Сырые события +CREATE TABLE events ( + id INTEGER PRIMARY KEY, + source TEXT, -- plane/gitea + event_type TEXT, + payload TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +## Deployment + +### Docker Compose + +```yaml +services: + orchestrator: + build: . + container_name: orchestrator + restart: unless-stopped + network_mode: host + volumes: + - ./data:/app/data # SQLite + logs + - /home/slin/repos:/repos # Git repositories + - /var/run/docker.sock:/var/run/docker.sock # Docker CLI + - claude-code:/opt/claude-code:ro # Claude CLI binary + - /home/slin/.claude:/home/slin/.claude # Claude config + env_file: .env + group_add: ["999"] # docker group +``` + +### Dockerfile + +- Base: python:3.12-slim +- Docker CLI (sibling containers) +- **tini** как PID 1 (proper zombie reaping) +- `git config --global safe.directory '*'` +- ENTRYPOINT: tini → uvicorn + +## Потоки данных + +### Happy path (ET-006 пример) + +``` +1. Plane webhook: work_item.created → task created, analyst launched +2. Analyst: пишет BRD/TRZ/AC/TestPlan → git push docs/ +3. Gitea push webhook: docs/ detected → QG check_analysis_complete → PASS +4. Auto-advance: analysis → architecture, architect launched +5. Architect: пишет ADR, infra-requirements → git push docs/ +6. Gitea push webhook: ADR detected → QG check_architecture_done → PASS +7. Auto-advance: architecture → development, developer launched +8. Developer: пишет код src/ + tests/ → git push, creates PR +9. Gitea status webhook: CI green → QG check_ci_green → PASS +10. Auto-advance: development → review, reviewer launched +11. Reviewer: оставляет review (APPROVED или REQUEST_CHANGES) +12. Gitea PR webhook: review event → QG check_review_approved → PASS +13. Advance: review → testing, tester launched +14. Tester: прогоняет тесты, пишет test-report.md → git push +15. Auto-advance: testing → deploy (QG check_tests_passed → PASS) +16. PR merge → Gitea PR webhook: action=closed, merged=true → done +``` + +### Review bounce path + +``` +11. Reviewer: REQUEST_CHANGES +12. Gitea PR webhook: review_state=REQUEST_CHANGES, stage=review +13. Rollback: review → development, developer relaunched (attempt N/3) +14. Developer: фиксит замечания → git push +15. CI green → development → review, reviewer relaunched +16. Reviewer: APPROVED → continue happy path +``` + +## Resilience + +| Механизм | Описание | +|----------|----------| +| Orphan recovery | При старте: runs без finished_at старше 35 мин → exit_code=-1 | +| Watchdog | Каждый агент: timeout 30 мин → SIGKILL + exit_code=-9 | +| tini | PID 1 reaper — zombie processes невозможны | +| safe.directory | git операции работают в любой директории | +| Stale review skip | check_review_approved игнорирует stale reviews | +| Max retries | Developer: max 3 попытки, затем эскалация | + +## Агенты + +Каждый агент — Claude CLI с: +- **System prompt**: `.openclaw/agents/{role}.md` (в репозитории) +- **Task file**: `.task-{suffix}.md` (генерируется orchestrator) +- **Tools**: Read, Write, Edit, Bash +- **Output**: `--print` mode (весь вывод в stdout после завершения) + +| Агент | Артефакты | Время (типичное) | +|-------|-----------|-------------------| +| analyst | BRD, TRZ, AC, TestPlan | 5-10 мин | +| architect | ADR, infra-requirements, tech-risks | 5-10 мин | +| developer | src/, tests/, PR | 15-30 мин | +| reviewer | review report, PR review | 3-5 мин | +| tester | test-report.md, e2e results | 10-25 мин |