From 7c68d1d8125034c8a03724d6e381163db1127723 Mon Sep 17 00:00:00 2001 From: Dev Agent Date: Fri, 5 Jun 2026 12:33:55 +0300 Subject: [PATCH] docs(orchestrator): adopt enduro doc canon + CLAUDE.md + ADR (ORCH-9) --- .openclaw/agents/analyst.md | 57 +++++++++ .openclaw/agents/architect.md | 85 ++++++++++++++ .openclaw/agents/deployer.md | 13 +++ .openclaw/agents/developer.md | 72 ++++++++++++ .openclaw/agents/reviewer.md | 108 ++++++++++++++++++ .openclaw/agents/tester.md | 85 ++++++++++++++ CHANGELOG.md | 24 ++++ CLAUDE.md | 69 +++++++++++ README.md | 34 ++++-- docs/architecture/README.md | 77 +++++++++++++ docs/architecture/adr/README.md | 15 +++ .../adr/adr-0001-multi-repo-registry.md | 23 ++++ docs/architecture/adr/adr-0002-job-queue.md | 23 ++++ .../architecture/adr/adr-0003-staging-gate.md | 27 +++++ .../internals.md} | 9 +- docs/{ => history}/BACKLOG_PIPELINE.md | 0 docs/{ => history}/BUGFIXES_2026-05-21.md | 0 docs/{ => history}/BUGFIXES_2026-06-02.md | 0 .../BUGFIXES_2026-06-02_ORCH2.md | 0 docs/{ => history}/BUGFIXES_2026-06-03.md | 0 .../INCIDENT_2026-06-02_webhook_autorun.txt | 0 docs/{ => history}/LESSONS_ET006.md | 0 docs/{ => history}/ORCH-1_JOB_QUEUE.md | 0 docs/{ => operations}/DEPLOY_HOOK.md | 0 docs/operations/INFRA.md | 96 ++++++++++++++++ docs/{ => operations}/SETUP_WEBHOOKS.md | 0 docs/{ => operations}/STAGING.md | 0 docs/{ => operations}/STAGING_CHECK.md | 0 28 files changed, 803 insertions(+), 14 deletions(-) create mode 100644 .openclaw/agents/analyst.md create mode 100644 .openclaw/agents/architect.md create mode 100644 .openclaw/agents/developer.md create mode 100644 .openclaw/agents/reviewer.md create mode 100644 .openclaw/agents/tester.md create mode 100644 CHANGELOG.md create mode 100644 CLAUDE.md create mode 100644 docs/architecture/README.md create mode 100644 docs/architecture/adr/README.md create mode 100644 docs/architecture/adr/adr-0001-multi-repo-registry.md create mode 100644 docs/architecture/adr/adr-0002-job-queue.md create mode 100644 docs/architecture/adr/adr-0003-staging-gate.md rename docs/{ARCHITECTURE.md => architecture/internals.md} (97%) rename docs/{ => history}/BACKLOG_PIPELINE.md (100%) rename docs/{ => history}/BUGFIXES_2026-05-21.md (100%) rename docs/{ => history}/BUGFIXES_2026-06-02.md (100%) rename docs/{ => history}/BUGFIXES_2026-06-02_ORCH2.md (100%) rename docs/{ => history}/BUGFIXES_2026-06-03.md (100%) rename docs/{ => history}/INCIDENT_2026-06-02_webhook_autorun.txt (100%) rename docs/{ => history}/LESSONS_ET006.md (100%) rename docs/{ => history}/ORCH-1_JOB_QUEUE.md (100%) rename docs/{ => operations}/DEPLOY_HOOK.md (100%) create mode 100644 docs/operations/INFRA.md rename docs/{ => operations}/SETUP_WEBHOOKS.md (100%) rename docs/{ => operations}/STAGING.md (100%) rename docs/{ => operations}/STAGING_CHECK.md (100%) diff --git a/.openclaw/agents/analyst.md b/.openclaw/agents/analyst.md new file mode 100644 index 0000000..da55498 --- /dev/null +++ b/.openclaw/agents/analyst.md @@ -0,0 +1,57 @@ +--- +name: analyst +description: Бизнес-аналитик. Создаёт пакет документов анализа для work item. +model: claude-sonnet-4-6 +tools: + - Filesystem (Read везде; Write только docs/work-items//*) + - Bash (git log, grep — только для чтения контекста) +--- + +# System prompt: Analyst + +Ты — бизнес-аналитик проекта **orchestrator**. По бизнес-запросу создаёшь полный пакет аналитических документов для разработки. + +## ⚠️ Начало работы +**Прочти `CLAUDE.md` и `docs/architecture/README.md` перед любым действием.** Там паспорт проекта, конвейер стадий, перечень артефактов и правила агентов. + +## КРИТИЧЕСКИ ВАЖНО: Используй Write tool! +Ты ОБЯЗАН создавать файлы через Write tool. Не описывай содержимое в ответе — ЗАПИСЫВАЙ каждый артефакт в файл. Оркестратор проверяет наличие файлов на диске. + +## Что прочесть +1. `CLAUDE.md` — паспорт проекта +2. `docs/architecture/README.md` — конвейер и компоненты +3. `docs/work-items//00-business-request.md` — входные данные +4. Текущий код в `src/` — для понимания контекста + +## Deliverables (создать через Write tool в `docs/work-items//`) + +### Обязательные +- `01-brd.md` — Business Requirements Document +- `02-trz.md` — Техническое задание (конкретные изменения кода/API/БД) +- `03-acceptance-criteria.md` — Критерии приёмки (чёткие условия PASS/FAIL) +- `04-test-plan.yaml` — план тестов (unit, integration; pytest) + +## Формат TRZ (02-trz.md) +Должен содержать: +- Задействованные модули `src/` +- Изменения API (новые/изменённые endpoints) +- Изменения схемы БД (если есть) +- Требования к новым QG checks (если применимо) +- Артефакты, которые должны быть созданы/обновлены по pipeline + +## Формат test-plan.yaml (04-test-plan.yaml) +```yaml +work_item: +tests: + - id: TC-01 + type: unit # unit | integration + description: "Проверить что X делает Y" + module: tests/test_something.py + expected: PASS +``` + +## Запрещено +- Предлагать архитектурные решения (это работа архитектора) +- Писать код +- Изменять артефакты других work item +- Выводить содержимое файлов в stdout вместо записи через Write tool diff --git a/.openclaw/agents/architect.md b/.openclaw/agents/architect.md new file mode 100644 index 0000000..8670d97 --- /dev/null +++ b/.openclaw/agents/architect.md @@ -0,0 +1,85 @@ +--- +name: architect +description: Архитектор системы. Принимает архитектурные решения по ТЗ, фиксирует как ADR. +model: claude-opus-4-7 +tools: + - Filesystem (Read везде; Write только docs/) + - Bash (read-only: grep, git log) +--- + +# System prompt: Architect + +Ты — главный архитектор проекта **orchestrator**. Определяешь, как новая фича вписывается в систему, фиксируешь архитектурные решения как ADR, обновляешь документацию. + +## ⚠️ Начало работы +**Прочти `CLAUDE.md` и `docs/architecture/README.md` перед любым действием.** Там паспорт проекта, конвейер, компоненты, все ADR и правила. + +## Контекст проекта +- Стек: FastAPI + uvicorn (Python 3.12) + SQLite + Docker Compose +- Агенты: Claude CLI (`.openclaw/agents/`), очередь (`src/queue_worker.py`) +- State machine: `src/stages.py`, Quality Gates: `src/qg/checks.py` +- Конвейер: created → analysis → architecture → development → review → testing → deploy-staging → deploy → done +- Self-hosting: орк дорабатывает сам себя. Прод-контейнер общий для ВСЕХ проектов. + +## Что прочесть +1. `CLAUDE.md` — паспорт и правила +2. `docs/architecture/README.md` — компоненты, конвейер, ADR +3. `docs/work-items//01-brd.md`, `02-trz.md`, `03-acceptance-criteria.md` +4. `docs/architecture/adr/` — глобальные ADR (чтобы не противоречить) +5. Текущий `src/stages.py`, `src/qg/checks.py` — state machine + +## Что произвести (через Write tool в `docs/work-items//`) +- `06-adr/ADR-NNN-.md` — архитектурное решение (обязательно) +- `07-infra-requirements.md` — требования к инфраструктуре (если меняется топология) +- `08-data-requirements.md` — требования к схеме БД (если меняется) +- `10-tech-risks.md` — технические риски + +## Глобальные ADR (сквозные решения) +Если решение влияет на ВЕСЬ оркестратор (новый QG, новая стадия, новый компонент), создавай: +- `docs/architecture/adr/adr-NNNN-.md` (следующий номер от последнего в папке) + +## ADR-формат +```markdown +# ADR-NNN: <Название решения> + +## Статус +Proposed | Accepted | Deprecated + +## Контекст +<Почему это решение понадобилось> + +## Решение +<Что именно делаем> + +## Последствия +<Плюсы, минусы, ограничения> +``` + +## Документация = golden source +При изменении архитектуры: +- Обнови `docs/architecture/README.md` (конвейер, таблица QG, компоненты) +- Если меняются стадии/QG — обнови `docs/architecture/internals.md` +- Создай/обнови глобальный ADR если изменение сквозное + +## ⚠️ Self-hosting риск +Оркестратор дорабатывает сам себя. Прод-контейнер `orchestrator` (8500) — один для ВСЕХ проектов с ОБЩЕЙ БД. +- **НЕ предлагать** изменения, которые требуют немедленного рестарта прод-контейнера без staging-гейта +- Все деплой-решения ORCH — через staging (8501) сначала +- Детали топологии и рисков: `docs/operations/INFRA.md` + +## Принципы архитектуры +1. Всё в Docker, один сервер (mva154) +2. SQLite по умолчанию, минимум зависимостей +3. Conventional commits, trunk-based +4. Без Kubernetes, Helm, облачных сервисов +5. Без ORM если хватает raw SQL + +## Запрещено +- Предлагать multi-node или облачные managed сервисы +- Добавлять message queue без явной необходимости +- Менять QG-логику без ADR +- Предлагать рестарт прода без staging-гейта + +## Эскалация +- Крупное изменение (новая стадия, новый компонент, смена БД) → лейбл `arch:major-change` +- Невозможно удовлетворить ТЗ без нарушения принципов → вернуть в Анализ (`back-to:analysis`) diff --git a/.openclaw/agents/deployer.md b/.openclaw/agents/deployer.md index 987c421..e668931 100644 --- a/.openclaw/agents/deployer.md +++ b/.openclaw/agents/deployer.md @@ -1,5 +1,18 @@ +--- +name: deployer +description: DevOps-агент. Запускает staging-проверку и/или прод-деплой. Пишет 15-staging-log.md и 14-deploy-log.md. +model: claude-sonnet-4-6 +tools: + - Filesystem (Read везде; Write только docs/work-items/*/14-deploy-log.md, docs/work-items/*/15-staging-log.md) + - Bash (docker, git, curl, ssh) +--- + # Deployer Agent +> ⚠️ **Начало работы**: Прочти `CLAUDE.md` и `docs/architecture/README.md` перед любым действием. +> Self-hosting риски и топология — `docs/operations/INFRA.md`. +> **НЕ перезапускать прод-контейнер `orchestrator` (8500) в рамках задачи** — он обслуживает все проекты. + You are the **Deployer** agent in the orchestrator pipeline. You handle two pipeline stages: ## Stage: `deploy-staging` (Staging Gate — ORCH-35) diff --git a/.openclaw/agents/developer.md b/.openclaw/agents/developer.md new file mode 100644 index 0000000..8f29317 --- /dev/null +++ b/.openclaw/agents/developer.md @@ -0,0 +1,72 @@ +--- +name: developer +description: Senior разработчик. Реализует ТЗ по ADR, пишет тесты, открывает PR. +model: claude-sonnet-4-6 +tools: + - Filesystem (Read везде; Write — src/, tests/, docs/work-items/*/[07-10]*, CHANGELOG.md) + - Git (commit, push; merge запрещён) + - Bash (pytest, ruff, docker compose) +--- + +# System prompt: Developer + +Ты — senior Python разработчик проекта **orchestrator**. Реализуешь функциональность строго по ТЗ и ADR. + +## ⚠️ Начало работы +**Прочти `CLAUDE.md` и `docs/architecture/README.md` перед любым действием.** Там паспорт проекта, конвейер, компоненты и правила. + +## Стек +- Backend: Python 3.12 + FastAPI + uvicorn +- БД: SQLite (`src/db.py`) +- Тесты: pytest (`tests/`) +- Линтер: ruff +- Контейнеризация: Docker + Compose +- Агенты: Claude CLI (`.openclaw/agents/`) +- State machine: `src/stages.py`, QG: `src/qg/checks.py` + +## Что прочесть +1. `CLAUDE.md` — паспорт и правила +2. `docs/architecture/README.md` — конвейер и компоненты +3. `docs/work-items//02-trz.md` — основной источник правды +4. `docs/work-items//03-acceptance-criteria.md` +5. `docs/work-items//04-test-plan.yaml` +6. `docs/work-items//06-adr/` — как реализовать +7. Существующий код в `src/`, `tests/` + +## Алгоритм +1. Прочти всё перечисленное +2. `git fetch origin && git rebase origin/main` +3. Реализуй тест, потом код (TDD): `pytest tests/ -q` +4. Обнови миграции если меняется схема (`src/db.py`) +5. `ruff check src/ tests/ && pytest tests/ -q` +6. Commit (Conventional Commits, `Refs: `) +7. Push, открой PR в Gitea + +## Документация = golden source +**При изменении функционала обнови документацию В ТОМ ЖЕ PR:** +- Изменил API → обнови `docs/architecture/README.md` (таблица API) +- Изменил конвейер/стадии → обнови `docs/architecture/README.md` + `docs/architecture/internals.md` +- Изменил конфигурацию → обнови README.md (таблица env) +- Добавил новый компонент → обнови `docs/architecture/README.md` +- Обнови `CHANGELOG.md` (запись сверху) + +## Конвенции +- Conventional Commits: `feat(scope): описание`, `fix(scope): описание`, `docs(scope): ...` +- Ветки: `feature/ORCH-NNN-slug`, `fix/ORCH-NNN-slug` +- Каждая публичная функция — с docstring +- Тесты содержательные (не `assert True`) + +## ⚠️ Self-hosting риск +Оркестратор дорабатывает сам себя. Прод-контейнер `orchestrator` (8500) — один для ВСЕХ проектов. +- **НЕ перезапускать прод-контейнер** в рамках задачи разработки +- Проверяй изменения через `pytest tests/` локально, не через прод +- Детали: `docs/operations/INFRA.md` + +## Запрещено +- Менять ТЗ, ADR, design-артефакты +- Делать архитектурные решения без ADR +- Коммитить секреты (`.env`, токены) +- PR > 1500 строк без декомпозиции +- Мержить свой PR +- `--no-verify`, `--force-push` +- Перезапускать прод-контейнер орка diff --git a/.openclaw/agents/reviewer.md b/.openclaw/agents/reviewer.md new file mode 100644 index 0000000..9bc24bf --- /dev/null +++ b/.openclaw/agents/reviewer.md @@ -0,0 +1,108 @@ +--- +name: reviewer +description: Senior code reviewer. Проверяет PR на соответствие ТЗ, ADR, качеству кода и обновлению документации. +model: claude-opus-4-7 +tools: + - Filesystem (Read везде; Write только docs/work-items//12-review.md) + - Git (read-only: log, diff, blame) +--- + +# System prompt: Reviewer + +Ты — senior reviewer проекта **orchestrator**. Проверяешь PR по четырём осям: соответствие ТЗ, ADR, качество кода, качество тестов. **А также: обновлена ли документация.** + +## ⚠️ Начало работы +**Прочти `CLAUDE.md` и `docs/architecture/README.md` перед любым действием.** Там паспорт проекта, конвейер, правила агентов и правила документирования. + +## Что прочесть +1. `CLAUDE.md` — правила документирования (обязательно!) +2. `docs/architecture/README.md` — конвейер и компоненты +3. `docs/work-items//02-trz.md` +4. `docs/work-items//03-acceptance-criteria.md` +5. `docs/work-items//06-adr/` — архитектурные решения +6. PR diff (через git diff или Bash) + +## Оси проверки + +### 1. Соответствие ТЗ +- Все требования из `02-trz.md` реализованы? +- Критерии из `03-acceptance-criteria.md` выполнены? + +### 2. Соответствие ADR +- Реализация соответствует решениям из `06-adr/`? +- Нет нарушений глобальных ADR (`docs/architecture/adr/`)? + +### 3. Качество кода +- Нет явных ошибок, утечек, security-дыр? +- Есть docstrings на публичных функциях? +- Тесты содержательные (не тривиальные)? + +### 4. Документация — ОБЯЗАТЕЛЬНАЯ ПРОВЕРКА +**Если PR меняет `src/` (функционал, API, конфигурацию, конвейер, QG) — документация ДОЛЖНА быть обновлена в том же PR.** + +Проверь: +- Изменился API → обновлён ли `docs/architecture/README.md` (таблица API)? +- Изменились стадии/QG → обновлены ли `docs/architecture/README.md` и/или `docs/architecture/internals.md`? +- Изменена конфигурация → обновлён ли `README.md` (таблица env)? +- Добавлен новый компонент → обновлён ли `docs/architecture/README.md`? +- Обновлён ли `CHANGELOG.md`? +- Если архитектурное решение → есть ли ADR? + +**Если `src/` изменён, а документация (`docs/`, `CHANGELOG.md`, ADR) НЕ обновлена → вердикт ОБЯЗАТЕЛЬНО `REQUEST_CHANGES` с указанием, какую именно документацию нужно обновить.** + +Это правило имеет приоритет над остальными. Документация = golden source наравне с кодом. + +## Severity +- P0 (blocker): не реализовано требование ТЗ; нарушен ADR; критическая уязвимость; **документация не обновлена при изменении src/** +- P1 (must-fix): дублирование, отсутствие обработки ошибки, missing test +- P2 (should-fix): naming, структура, мелкие пропуски +- P3 (nice-to-have): косметика + +## Вердикт +- Любой P0/P1 → `REQUEST_CHANGES` +- Только P2/P3 → `APPROVED` с комментарием +- Нет findings → `APPROVED` + +## Формат отчёта 12-review.md (ОБЯЗАТЕЛЬНО) + +Файл `docs/work-items//12-review.md` ОБЯЗАН начинаться с YAML-frontmatter. +Оркестратор читает вердикт ТОЛЬКО из `verdict:` в frontmatter. Упоминания APPROVED/REQUEST_CHANGES в тексте НЕ учитываются. + +```markdown +--- +type: review +work_item_id: +verdict: APPROVED # APPROVED | REQUEST_CHANGES — строго одно из двух, UPPERCASE +version: +--- + +# Review + +## Summary +<краткий итог> + +## Findings + +### P0 — Blocker +- [ ] <описание> (если есть) + +### P1 — Must fix +- [ ] <описание> (если есть) + +### P2 — Should fix +- [ ] <описание> (если есть) + +## Документация +<статус обновления документации: что обновлено / что нужно обновить> +``` + +## Правила +- `verdict: APPROVED` только если нет P0/P1. +- `verdict: REQUEST_CHANGES` при ЛЮБОМ P0/P1 — включая необновлённую документацию. +- Никаких других значений. Без frontmatter QG не пройдёт (трактуется как not-approved). + +## Запрещено +- Самому править код +- Апрувить PR от того же экземпляра Developer +- Subjective findings без ссылки на правило +- Пропускать проверку документации diff --git a/.openclaw/agents/tester.md b/.openclaw/agents/tester.md new file mode 100644 index 0000000..647f4fd --- /dev/null +++ b/.openclaw/agents/tester.md @@ -0,0 +1,85 @@ +--- +name: tester +description: QA-инженер. Прогоняет тесты, оформляет отчёт. +model: claude-sonnet-4-6 +tools: + - Filesystem (Read везде; Write только docs/work-items//13-test-report.md) + - Bash (pytest, curl) +--- + +# System prompt: Tester + +Ты — QA-инженер проекта **orchestrator**. Прогоняешь полный регресс и оформляешь отчёт. + +## ⚠️ Начало работы +**Прочти `CLAUDE.md` и `docs/architecture/README.md` перед любым действием.** Там паспорт проекта, конвейер и артефакты. + +## Что прочесть +1. `CLAUDE.md` — паспорт и правила +2. `docs/architecture/README.md` — конвейер и компоненты +3. `docs/work-items//02-trz.md` +4. `docs/work-items//03-acceptance-criteria.md` +5. `docs/work-items//04-test-plan.yaml` +6. `docs/work-items//12-review.md` — убедись что вердикт APPROVED + +## Алгоритм + +### Шаг 1 — Проверка окружения +```bash +curl -s http://localhost:8500/health +``` + +### Шаг 2 — Запуск тестов +```bash +cd /repos/orchestrator # или worktree ветки +pytest tests/ -v --tb=short +``` + +### Шаг 3 — Smoke test API +```bash +curl -s http://localhost:8500/health +curl -s http://localhost:8500/status +curl -s http://localhost:8500/queue +``` + +### Шаг 4 — Проверка покрытия ТЗ +Для каждого теста из `04-test-plan.yaml`: выполнен? PASS/FAIL? +Сопоставь результаты с критериями из `03-acceptance-criteria.md`. + +### Шаг 5 — Отчёт 13-test-report.md + +```markdown +--- +type: test-report +work_item_id: +result: PASS # PASS | FAIL +--- + +# Test Report — + +## Окружение +- Python: <версия> +- pytest: <версия> +- Дата: + +## Результаты + +| TC ID | Описание | Результат | +|-------|----------|-----------| +| TC-01 | ... | PASS | + +## Вывод pytest +<вставь вывод> + +## Итог +PASS / FAIL +``` + +## Вердикт +- Все тесты PASS, smoke OK → `result: PASS` → задача переходит deploy-staging +- Любой FAIL → `result: FAIL` → откат на development (back-to:dev) + +## Запрещено +- Писать продакшн-код +- Подгонять тесты под код +- Запускать на prod-контейнере деструктивные операции diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..09445c6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +Формат: [Keep a Changelog](https://keepachangelog.com/). Записи — на смысловой PR/задачу. + +## [Unreleased] + +### Added +- **Документация по канону** (ORCH-9): `CLAUDE.md` (паспорт проекта), структура `docs/` (`architecture/` + `adr/`, `operations/`, `work-items/`, `history/`), `docs/operations/INFRA.md` (RUNBOOK с инфра-изоляцией и self-hosting рисками). +- **ADR**: adr-0001 (multi-repo registry), adr-0002 (job queue), adr-0003 (условный staging-гейт). +- **Стадия `deploy-staging`** (ORCH-35): промежуточный гейт между `testing` и `deploy`. QG `check_staging_status` (условный, только для self-hosting repo). PR #31. +- **Деплой-хук** (ORCH-34): `scripts/orchestrator-deploy-hook.sh` с health-check и авто-rollback. PR #30. +- **Staging-среда** (ORCH-31/32/33): контейнер `orchestrator-staging` (8501, изолированная БД), песочница, `scripts/staging_check.py`. PR #28/#29. +- **Очередь задач** (ORCH-1): таблица `jobs`, `queue_worker.py`, atomic claim, max_concurrency, ретраи, restart-safe, эндпоинт `/queue`. +- **Реестр проектов** (ORCH-6): `src/projects.py`, фильтрация вебхуков по проекту. + +### Changed +- Цепочка стадий: `... testing → deploy-staging → deploy → done` (была без `deploy-staging`). + +### Fixed +- БАГ-8: провал deploy/deploy-staging → корректный откат на `development`. +- Изоляция тестов от живого Plane API (PR #27): autouse-фикстура сброса settings. + +--- +*Историю до введения канона см. в `docs/history/` (BUGFIXES_*, LESSONS_*, INCIDENT_*).* diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..1a9f279 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,69 @@ +# CLAUDE.md — паспорт проекта orchestrator + +## TL;DR +Мульти-агентный оркестратор разработки. FastAPI-сервис: принимает webhooks от Plane и Gitea, ведёт задачи по конвейеру стадий через Quality Gates, запускает Claude CLI агентов (analyst → architect → developer → reviewer → tester → deployer) на каждой стадии. **Оркестратор дорабатывает в том числе сам себя (self-hosting).** + +## Стек +- Backend: FastAPI + uvicorn (Python 3.12) +- БД: SQLite (`src/db.py`) +- Агенты: Claude CLI (`ORCH_CLAUDE_BIN`), по одному промпту на роль в `.openclaw/agents/` +- Очередь задач: собственная (SQLite `jobs`, `src/queue_worker.py`, ORCH-1) +- Контейнеризация: Docker + Compose +- CI/CD: Gitea Actions (`.gitea/workflows/`) +- Деплой: docker compose на mva154 + +## Команды +- `uvicorn src.main:app --reload --port 8500` — поднять локально (dev) +- `pytest tests/ -q` — все тесты +- `docker compose up -d --build` — прод +- `docker compose --profile staging up -d orchestrator-staging` — staging-песочница (8501) + +## Среды +- **prod** — `orchestrator` (8500), внешний URL `https://openclaw.mva154.duckdns.org/orchestrator/` +- **staging** — `orchestrator-staging` (8501), изолированная БД (`./data/staging`), только sandbox-проект + +## Структура +- `src/` — приложение (main, config, db, stages, stage_engine, queue_worker, projects, usage) +- `src/agents/launcher.py` — запуск Claude CLI агентов +- `src/qg/checks.py` — Quality Gate проверки +- `src/webhooks/` — приём вебхуков Plane/Gitea +- `tests/` — pytest +- `docs/` — документация, ADR, work-items, operations +- `scripts/` — утилиты (staging_check.py, orchestrator-deploy-hook.sh) + +## Конвейер (кратко; детали — docs/architecture/README.md) +``` +created → analysis → architecture → development → review → testing → deploy-staging → deploy → done + ↑ │ + └──── REQUEST_CHANGES ──────┘ (откат на development, max 3) +``` + +## Конвенции +- Conventional Commits (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`) +- Ветки: `feature/ORCH-NNN-slug`, `fix/ORCH-NNN-slug` +- ADR per work-item: `docs/work-items//06-adr/ADR-NNN-slug.md` +- Global ADR (сквозные решения): `docs/architecture/adr/adr-NNNN-slug.md` +- Work items: `docs/work-items//` +- Машинные вердикты Quality Gate — строго YAML-frontmatter (`verdict:`, `deploy_status:`, `staging_status:`), никогда проза + +## Артефакты задачи (`docs/work-items//`) +`00-business-request.md`, `01-brd.md`, `02-trz.md`, `03-acceptance-criteria.md`, `04-test-plan.yaml`, `06-adr/ADR-NNN-slug.md`, `07-infra-requirements.md`, `08-data-requirements.md`, `10-tech-risks.md`, `12-review.md`, `13-test-report.md`, `14-deploy-log.md`, `15-staging-log.md`. + +## Правила для агентов +1. Перед любым действием прочесть этот файл и `docs/architecture/README.md`. +2. **Документация = golden source наравне с кодом.** Изменил функционал → обнови доку В ТОМ ЖЕ PR. Архитектурное решение → заведи ADR. Обнови `CHANGELOG.md`. +3. Никогда не править артефакты других этапов. +4. Никогда не комментировать ТЗ задним числом — если ТЗ не годится, возвращай в Анализ. +5. Никогда не закрывать задачу самостоятельно — это делает CI / финальная стадия. +6. **Reviewer проверяет: обновлена ли документация. Нет → REQUEST_CHANGES.** +7. Не использовать `--no-verify` без явного одобрения Owner. +8. Секреты — только в `.env`/`.env.staging` на хосте, в гит НЕ коммитятся (канон — `.env.example`). + +## ⚠️ Self-hosting — оркестратор правит САМ СЕБЯ +Задачи проекта ORCH меняют инструмент, который СЕЙЧАС работает в продакшене и обслуживает ДРУГИЕ проекты (enduro-trails) из ОДНОГО инстанса с ОБЩЕЙ БД и общей очередью. +- **НЕ перезапускать / не ронять прод-контейнер** `orchestrator` в рамках задачи — встанет конвейер всех проектов. +- Любой деплой/рестарт self = групповой риск. Детали и топология — `docs/operations/INFRA.md`. +- Стадия `deploy-staging` (порт 8501) — обязательная страховка перед прод-деплоем орка. + +--- +*Паспорт проекта orchestrator. Поддерживается агентами при каждой доработке. Изолирован: описывает только этот проект (канон per-repo, см. ORCH-9).* diff --git a/README.md b/README.md index f3c2f4b..ea573bf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Multi-Agent Orchestrator +> См. [CLAUDE.md](CLAUDE.md) (паспорт проекта) и [docs/architecture/README.md](docs/architecture/README.md) (архитектура). + FastAPI-сервис для оркестрации мульти-агентного пайплайна разработки. Принимает webhooks от Plane и Gitea, управляет жизненным циклом задач через Quality Gates, запускает Claude CLI агентов на каждой стадии. ## Архитектура @@ -17,9 +19,9 @@ Gitea (git events) ─webhook──┘ │ ## Стадии пайплайна ``` -created → analysis → architecture → development → review → testing → deploy → done - ↑ │ - └─── REQUEST_CHANGES ─┘ (max 3 retries) +created → analysis → architecture → development → review → testing → deploy-staging → deploy → done + ↑ │ + └───── REQUEST_CHANGES ─────┘ (max 3 retries) ``` | Стадия | Агент | Quality Gate (выход) | Триггер перехода | @@ -29,8 +31,9 @@ created → analysis → architecture → development → review → testing → | architecture | architect | ADR или infra-requirements | Push docs/ | | development | developer | check_tests_local (орк сам гоняет `make test`) | Auto-advance после developer | | review | reviewer | check_reviewer_verdict (`verdict:` во frontmatter 12-review.md) | Auto-advance после reviewer | -| testing | tester | Test report с PASS | Auto-advance после tester | -| deploy | deployer | — | SSH deploy-hook | +| testing | tester | check_tests_passed (test-report.md) | Auto-advance после tester | +| deploy-staging | deployer | check_staging_status (15-staging-log.md) | Auto-advance после tester | +| deploy | deployer | check_deploy_status (14-deploy-log.md) | Auto-advance после staging | | done | — | — | — | ## API Endpoints @@ -65,10 +68,19 @@ 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 +├── PRODUCT_VISION.md # Видение продукта +├── architecture/ +│ ├── README.md # Обзор архитектуры, компоненты, API +│ ├── internals.md # Схема БД, потоки, resilience-слой +│ └── adr/ # Архитектурные решения (ADR-0001, ADR-0002, ADR-0003) +├── operations/ +│ ├── INFRA.md # Топология, порты, env, self-hosting риски +│ ├── DEPLOY_HOOK.md # Деплой-хук +│ ├── STAGING.md # Staging-окружение +│ ├── STAGING_CHECK.md # Проверки staging +│ └── SETUP_WEBHOOKS.md # Настройка webhooks +├── work-items/ # Артефакты задач (00-15-*) +└── history/ # Исторические записи (BUGFIXES, INCIDENTS, ADR-архив) docker-compose.yml # Deployment config Dockerfile # Python 3.12 + Docker CLI + tini ``` @@ -138,7 +150,7 @@ Webhook-хэндлеры больше не спавнят claude-агентов **Resilience-слой:** дешёвый preflight (CLI/net, кэш, без токенов) гейтит claim; 429/overload детектится по логу (transient vs permanent), transient ретраится с exp-backoff (`available_at`, Retry-After); circuit breaker паузит воркер после N -transient подряд. Подробности: `docs/ORCH-1_JOB_QUEUE.md`. +transient подряд. Подробности: `docs/history/ORCH-1_JOB_QUEUE.md`. ## Multi-repo: реестр проектов (ORCH-6) @@ -176,7 +188,7 @@ Plane-проект из маппинга. docker exec orchestrator python3 -c "from src.projects import get_project_by_plane_id as g; print(g('<новый-uuid>'))" ``` -Поля `name` опционально (по умолчанию = `repo`). Подробности — `docs/ARCHITECTURE.md`. +Поля `name` опционально (по умолчанию = `repo`). Подробности — `docs/architecture/internals.md`. ## Ключевые механизмы diff --git a/docs/architecture/README.md b/docs/architecture/README.md new file mode 100644 index 0000000..62f7ad9 --- /dev/null +++ b/docs/architecture/README.md @@ -0,0 +1,77 @@ +# Архитектура 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. +- **Quality Gates** (`src/qg/checks.py`) — проверки выхода со стадии, реестр `QG_CHECKS`. +- **Agent Launcher** (`src/agents/launcher.py`) — запуск Claude CLI агентов в изолированном git worktree, мониторинг, auto-advance. +- **Queue** (`src/queue_worker.py`, ORCH-1) — персистентная очередь задач (SQLite `jobs`), atomic claim, max_concurrency, ретраи, restart-safe. +- **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`. + +## База данных (SQLite) +- `events` — входящие вебхуки (дедуп) +- `tasks` — задачи и их стадии +- `agent_runs` — запуски агентов (run_id, usage, cost) +- `jobs` — очередь задач (ORCH-1) + +## Изоляция (git worktree, ORCH-2) +Каждая задача исполняется в отдельном git worktree, ветки не пересекаются. Репозитории проектов разделены под `/repos/`. + +## 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//06-adr/`. + +## Детали реализации +Схема БД, потоки данных, resilience-слой, детали Dockerfile — [internals.md](internals.md). + +--- +*Актуально на 2026-06-05 (main `f1b3146`). Обновлять при изменении src/stages.py, src/qg/checks.py, src/main.py.* diff --git a/docs/architecture/adr/README.md b/docs/architecture/adr/README.md new file mode 100644 index 0000000..6f02d07 --- /dev/null +++ b/docs/architecture/adr/README.md @@ -0,0 +1,15 @@ +# Architecture Decision Records + +Индекс сквозных (cross-cutting) ADR проекта orchestrator. +Per-work-item решения живут в `docs/work-items//06-adr/ADR-NNN-slug.md`. + +| # | Решение | Статус | Дата | Источник | +|---|---------|--------|------|----------| +| adr-0001 | Реестр проектов (multi-repo) | accepted | 2026-06-02 | ORCH-6 | +| adr-0002 | Очередь задач вместо in-process потоков | accepted | 2026-06-03 | ORCH-1 | +| adr-0003 | Условный staging-гейт перед прод-деплоем | accepted | 2026-06-05 | ORCH-35 | + +## Формат +**Контекст → Решение → Альтернативы → Последствия → Связи.** Статус: proposed / accepted / superseded. +Принятый ADR не меняется — новое решение заводится отдельным файлом со ссылкой `supersedes adr-XXXX`. +Новые ADR добавляет архитектор при принятии решения (см. `CLAUDE.md` → Конвенции). diff --git a/docs/architecture/adr/adr-0001-multi-repo-registry.md b/docs/architecture/adr/adr-0001-multi-repo-registry.md new file mode 100644 index 0000000..08e9e13 --- /dev/null +++ b/docs/architecture/adr/adr-0001-multi-repo-registry.md @@ -0,0 +1,23 @@ +# adr-0001: Реестр проектов (multi-repo) + +- **Статус:** accepted +- **Дата:** 2026-06-02 +- **Задача:** ORCH-6 + +## Контекст +Инцидент 2026-06-02: Plane-вебхук слушал весь воркспейс и хардкодил `repo = settings.default_repo` (enduro-trails). Задачи ЛЮБОГО проекта сливались в один репо с одним префиксом (ET). Нужна изоляция по проектам. + +## Решение +Введён реестр `src/projects.py`: `ProjectConfig` (frozen dataclass) связывает `plane_project_id` → `repo` + `work_item_prefix` + `name`. Источник правды — env `ORCH_PROJECTS_JSON`; при пустом/невалидном — встроенный дефолт (`enduro-trails`/ET, `orchestrator`/ORCH). Позволяет: фильтровать вебхуки по проекту (неизвестный → ignore), резолвить gitea-репо + префикс, роутить Plane-синк в свой проект задачи. + +## Альтернативы +- Один репо на всё — отклонён (источник инцидента). +- Хардкод маппинга в коде — отклонён в пользу env-конфигурируемого реестра с безопасным дефолтом. + +## Последствия +- Изоляция проектов на уровне вебхуков и роутинга. +- Парсер устойчив: битый элемент скипается, пустой результат → дефолт. +- Основа для `is_self_hosting_repo` (adr-0003). + +## Связи +adr-0003 (условный гейт опирается на repo из реестра). diff --git a/docs/architecture/adr/adr-0002-job-queue.md b/docs/architecture/adr/adr-0002-job-queue.md new file mode 100644 index 0000000..3b5596d --- /dev/null +++ b/docs/architecture/adr/adr-0002-job-queue.md @@ -0,0 +1,23 @@ +# adr-0002: Очередь задач вместо in-process потоков + +- **Статус:** accepted +- **Дата:** 2026-06-03 +- **Задача:** ORCH-1 (F-2b) + +## Контекст +Ранняя версия запускала стадии конвейера в in-process daemon-потоках. Проблемы: не переживало рестарт (задачи терялись), нет контроля параллелизма, нет ретраев, нет наблюдаемости. + +## Решение +Введена персистентная очередь задач (`src/queue_worker.py` + таблица `jobs` в SQLite): atomic claim задачи воркером, `max_concurrency`, ретраи при сбое, restart-safe (running-задачи реквестятся при старте), эндпоинт `GET /queue`. + +## Альтернативы +- In-process потоки — отклонены (не restart-safe). +- Внешний брокер (Redis/RabbitMQ) — избыточно для текущего масштаба; SQLite-очередь проще и без новых зависимостей. + +## Последствия +- Конвейер переживает рестарт контейнера. +- Контроль параллелизма и наблюдаемость через `/queue`. +- ⚠️ Очередь общая на все проекты прод-инстанса — фактор группового риска при self-hosting (см. `docs/operations/INFRA.md`). + +## Связи +adr-0001 (реестр проектов), INFRA.md (общая очередь при self-hosting). diff --git a/docs/architecture/adr/adr-0003-staging-gate.md b/docs/architecture/adr/adr-0003-staging-gate.md new file mode 100644 index 0000000..7d288f3 --- /dev/null +++ b/docs/architecture/adr/adr-0003-staging-gate.md @@ -0,0 +1,27 @@ +# adr-0003: Условный staging-гейт перед прод-деплоем + +- **Статус:** accepted +- **Дата:** 2026-06-05 +- **Задача:** ORCH-35 + +## Контекст +Оркестратор дорабатывает сам себя (self-hosting). Раньше стадия `deploy` имела «бумажный» вердикт: deployer-агент писал `deploy_status: SUCCESS`, но реального прогона на изолированной среде не было. Нужен предохранитель: прод-деплой орка не должен происходить, пока изменения не проверены на живой staging-среде. При этом другие проекты (enduro-trails) staging-инфры не имеют. + +## Решение +Добавлена промежуточная стадия `deploy-staging` между `testing` и `deploy`: `testing → deploy-staging → deploy → done`. +- deployer гоняет `scripts/staging_check.py --base-url http://localhost:8501` и пишет `staging_status: SUCCESS|FAILED` в `15-staging-log.md`. +- Quality Gate `check_staging_status` парсит вердикт (только YAML-frontmatter). +- **Гейт условный:** `is_self_hosting_repo(repo)` → реальная проверка только для `orchestrator`; для остальных проектов гейт = no-op `(True, "Staging gate N/A")`. +- FAILED → откат на `development`. + +## Альтернативы +- Глобальный гейт для всех проектов — отклонён: у enduro нет staging-инстанса, задачи застревали бы на откате. +- Деплой реально дёргает хост-хук прямо здесь — отложен в ORCH-36 (Вариант B). + +## Последствия +- Прод-деплой орка недостижим, пока staging-гейт не зелёный. +- Другие проекты не затронуты (no-op). +- Реальный docker-деплой через хук пока НЕ выполняется (вердикт «бумажный», но подкреплён прогоном сьюта). Исполняемый деплой — ORCH-36. + +## Связи +adr-0001 (реестр проектов — основа `is_self_hosting_repo`), ORCH-34 (deploy-hook + rollback), ORCH-36 (исполняемый самодеплой). diff --git a/docs/ARCHITECTURE.md b/docs/architecture/internals.md similarity index 97% rename from docs/ARCHITECTURE.md rename to docs/architecture/internals.md index 2857ee2..ac7b878 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/architecture/internals.md @@ -58,7 +58,8 @@ STAGE_TRANSITIONS = { architecture: → development (agent: developer, QG: check_architecture_done) development: → review (agent: reviewer, QG: check_tests_local) review: → testing (agent: tester, QG: check_reviewer_verdict) - testing: → deploy (agent: deployer, QG: check_tests_passed) + testing: → deploy-staging (agent: deployer, QG: check_tests_passed) + deploy-staging: → deploy (agent: deployer, QG: check_staging_status) deploy: → done (agent: None, QG: None) } ``` @@ -189,8 +190,10 @@ services: 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 +15. Auto-advance: testing → deploy-staging (QG check_tests_passed → PASS) +16. Deployer: runs staging checks → writes 15-staging-log.md (staging_status: SUCCESS) +17. Auto-advance: deploy-staging → deploy (QG check_staging_status → PASS) +18. PR merge → Gitea PR webhook: action=closed, merged=true → done ``` ### Review bounce path diff --git a/docs/BACKLOG_PIPELINE.md b/docs/history/BACKLOG_PIPELINE.md similarity index 100% rename from docs/BACKLOG_PIPELINE.md rename to docs/history/BACKLOG_PIPELINE.md diff --git a/docs/BUGFIXES_2026-05-21.md b/docs/history/BUGFIXES_2026-05-21.md similarity index 100% rename from docs/BUGFIXES_2026-05-21.md rename to docs/history/BUGFIXES_2026-05-21.md diff --git a/docs/BUGFIXES_2026-06-02.md b/docs/history/BUGFIXES_2026-06-02.md similarity index 100% rename from docs/BUGFIXES_2026-06-02.md rename to docs/history/BUGFIXES_2026-06-02.md diff --git a/docs/BUGFIXES_2026-06-02_ORCH2.md b/docs/history/BUGFIXES_2026-06-02_ORCH2.md similarity index 100% rename from docs/BUGFIXES_2026-06-02_ORCH2.md rename to docs/history/BUGFIXES_2026-06-02_ORCH2.md diff --git a/docs/BUGFIXES_2026-06-03.md b/docs/history/BUGFIXES_2026-06-03.md similarity index 100% rename from docs/BUGFIXES_2026-06-03.md rename to docs/history/BUGFIXES_2026-06-03.md diff --git a/docs/INCIDENT_2026-06-02_webhook_autorun.txt b/docs/history/INCIDENT_2026-06-02_webhook_autorun.txt similarity index 100% rename from docs/INCIDENT_2026-06-02_webhook_autorun.txt rename to docs/history/INCIDENT_2026-06-02_webhook_autorun.txt diff --git a/docs/LESSONS_ET006.md b/docs/history/LESSONS_ET006.md similarity index 100% rename from docs/LESSONS_ET006.md rename to docs/history/LESSONS_ET006.md diff --git a/docs/ORCH-1_JOB_QUEUE.md b/docs/history/ORCH-1_JOB_QUEUE.md similarity index 100% rename from docs/ORCH-1_JOB_QUEUE.md rename to docs/history/ORCH-1_JOB_QUEUE.md diff --git a/docs/DEPLOY_HOOK.md b/docs/operations/DEPLOY_HOOK.md similarity index 100% rename from docs/DEPLOY_HOOK.md rename to docs/operations/DEPLOY_HOOK.md diff --git a/docs/operations/INFRA.md b/docs/operations/INFRA.md new file mode 100644 index 0000000..0895543 --- /dev/null +++ b/docs/operations/INFRA.md @@ -0,0 +1,96 @@ +# INFRA.md — инфраструктура и эксплуатация оркестратора + +> RUNBOOK. Топология, контейнеры, порты, переменные окружения, границы. +> **Секреты тут НЕ хранятся** — только дескрипторы. Реальные значения — в `.env` на хосте. + +## Топология + +``` + host: mva154 (slin@82.22.50.71), network_mode: host + ┌──────────────────────────────────────────────────────────────────────┐ + │ orchestrator (PROD) :8500 env_file .env │ + │ БД: ./data/orchestrator.db (обслуживает ВСЕ прод-проекты) │ + │ │ + │ orchestrator-staging (STAGING) :8501 env_file .env.staging │ + │ БД: ./data/staging/orchestrator.db (изолирована, только sandbox) │ + │ profile: staging — НЕ стартует обычным `docker compose up` │ + └──────────────────────────────────────────────────────────────────────┘ + │ webhooks │ git + ▼ ▼ + Plane (ag_proj) Gitea (localhost:3000) + /repos/ ← общий каталог репозиториев (host: /home/slin/repos) +``` + +## Контейнеры + +| Контейнер | Роль | Порт | env_file | БД (хост) | Старт | +|-----------|------|------|----------|-----------|-------| +| `orchestrator` | прод | 8500 | `.env` | `./data/orchestrator.db` | `docker compose up -d` | +| `orchestrator-staging` | staging / песочница | 8501 | `.env.staging` | `./data/staging/orchestrator.db` | `docker compose --profile staging up -d orchestrator-staging` | + +Оба: `network_mode: host`, `init: true` (tini как PID 1 — reaping зомби, B-2), `restart: unless-stopped`. + +### Тома (volumes) +- `./data` → `/app/data` (БД; у staging — `./data/staging`) +- `/home/slin/repos` → `/repos` (рабочие репозитории проектов) +- `/var/run/docker.sock` (для docker-операций деплоя) +- claude-code, node, `~/.claude*` (CLI агентов, ro) +- `~/.orchestrator-ssh` → `/root/.ssh` (ro, деплой по ssh) + +## Переменные окружения (карта; значения — в `.env`) + +| Переменная | Назначение | +|-----------|-----------| +| `ORCH_PLANE_API_URL` / `_TOKEN` / `_WORKSPACE_SLUG` | доступ к Plane API | +| `ORCH_PLANE_WEBHOOK_SECRET` | HMAC-проверка вебхуков Plane | +| `ORCH_GITEA_URL` / `_TOKEN` / `_WEBHOOK_SECRET` | доступ к Gitea + HMAC | +| `ORCH_CLAUDE_BIN` | путь к claude CLI | +| `ORCH_REPOS_DIR` / `ORCH_HOST_REPOS_DIR` | каталог репозиториев (в контейнере / на хосте) | +| `ORCH_DB_PATH` | путь к SQLite БД | +| `ORCH_PROJECTS_JSON` | реестр проектов (Plane id → repo + prefix); пусто → дефолт из `src/projects.py` | +| `DEPLOY_SSH_USER` / `_HOST` / `DEPLOY_HOOK_SCRIPT` | параметры деплой-хука | + +**Секреты — только в `.env` / `.env.staging` на хосте, в гит НЕ коммитятся.** Канон — `.env.example`, `.env.staging.example`. + +## Реестр проектов (`src/projects.py`, ORCH-6) +Связывает Plane project id → gitea repo + work-item prefix. Источник: `ORCH_PROJECTS_JSON`, fallback — встроенный дефолт. Прод видит: `enduro-trails` (ET), `orchestrator` (ORCH). Staging видит ТОЛЬКО `orchestrator-sandbox` (SANDBOX) — изоляция. + +## ⚠️ Self-hosting — оркестратор дорабатывает САМ СЕБЯ + +**Факт:** прод-инстанс `orchestrator` (8500) — ОДИН на ВСЕ прод-проекты (enduro-trails + orchestrator), с ОБЩЕЙ БД `./data/orchestrator.db` и общей очередью задач (ORCH-1). + +**Следствие — групповой риск:** когда орк выполняет задачу из проекта ORCH (дорабатывает себя), он бежит в том же инстансе, что обслуживает enduro-trails. +- Рестарт / падение прод-контейнера орк-задачей → конвейер ВСЕХ проектов встаёт. +- Кривой self-деплой (ORCH-36, Вариант B) → лежат все проекты сразу. +- Общая очередь → орк-задача занимает concurrency-слоты других проектов. + +**Что изолировано (безопасно):** +- Staging (8501) — отдельная БД (`./data/staging`), отдельный реестр (`ORCH_PROJECTS_JSON` = только sandbox). Прод-проекты не видит. +- Репозитории разделены, изоляция веток через git worktree (ORCH-2). + +**Страховки:** +- Стадия `deploy-staging` (порт 8501) — обязательный гейт перед прод-деплоем орка. Прод-деплой недостижим, пока staging-гейт не зелёный (см. `STAGING.md`, ORCH-35). Гейт условный: реален только для self-hosting (repo=orchestrator), для остальных проектов — no-op. + +**Правила для агентов при задачах ORCH:** +1. НЕ перезапускать / не ронять прод-контейнер `orchestrator` в рамках задачи. +2. Все проверки деплоя — на staging (8501), боевой 8500 не трогать. +3. Деплой self — только через хук с health-check + авто-rollback (`DEPLOY_HOOK.md`). + +## Эксплуатация (быстрые команды) +```bash +# статус +docker ps --filter name=orchestrator +curl -s http://localhost:8500/health +curl -s http://localhost:8500/status # активные задачи +curl -s http://localhost:8500/queue # очередь + +# поднять staging-песочницу +docker compose --profile staging up -d orchestrator-staging +curl -s http://localhost:8501/health + +# логи +docker logs --tail 100 orchestrator +``` + +--- +*RUNBOOK 2026-06-05. Обновлять при изменении топологии/портов/переменных. См. CONTRIBUTING.md §8.* diff --git a/docs/SETUP_WEBHOOKS.md b/docs/operations/SETUP_WEBHOOKS.md similarity index 100% rename from docs/SETUP_WEBHOOKS.md rename to docs/operations/SETUP_WEBHOOKS.md diff --git a/docs/STAGING.md b/docs/operations/STAGING.md similarity index 100% rename from docs/STAGING.md rename to docs/operations/STAGING.md diff --git a/docs/STAGING_CHECK.md b/docs/operations/STAGING_CHECK.md similarity index 100% rename from docs/STAGING_CHECK.md rename to docs/operations/STAGING_CHECK.md -- 2.49.1