170 lines
12 KiB
Markdown
170 lines
12 KiB
Markdown
# BRD — ET-015 / ORCH-6: Multi-repo support для оркестратора
|
||
|
||
Work Item ID: ET-015
|
||
Plane title: [ORCH-6] Multi-repo: оркестратор работает по нескольким проектам
|
||
Целевой репозиторий изменений: `orchestrator` (а не `enduro-trails`)
|
||
Где трекается work item: `enduro-trails/docs/work-items/ET-015/` (организационная задача)
|
||
|
||
## 1. Контекст и проблема
|
||
|
||
Multi-Agent Orchestrator (FastAPI-сервис на порту 8500) сегодня жёстко
|
||
завязан на один проект — `enduro-trails`. Это видно по нескольким местам:
|
||
|
||
1. `ORCH_DEFAULT_REPO=enduro-trails` — единственный fallback, который
|
||
используется почти везде в `webhooks/plane.py`, `webhooks/gitea.py`,
|
||
`agents/launcher.py`.
|
||
2. Префикс work item ID жёстко `ET-` (`get_next_work_item_id` в `db.py`,
|
||
строка ~93–99): любой новый таск, откуда бы он ни пришёл, получает
|
||
ID вида `ET-NNN`.
|
||
3. Plane-настройки одиночные: `ORCH_PLANE_WORKSPACE_SLUG`,
|
||
`ORCH_PLANE_PROJECT_ID`, словарь `PLANE_STATES` со state-id'ами
|
||
конкретного проекта `enduro-trails`. Webhooks от другого Plane-проекта
|
||
будут обработаны, но patch'и состояний и комментарии полетят в чужой
|
||
проект.
|
||
4. Документация (`docs/phases/PH-1..PH-9`, фазы roadmap), agent-prompts
|
||
(`.openclaw/agents/*.md`) и Quality Gates конвенции живут в `enduro-trails`
|
||
и неявно считаются «универсальными».
|
||
|
||
В результате невозможно подключить к оркестратору ни сам `orchestrator` (мета-разработка),
|
||
ни любой будущий проект (например `enduro-tiles-data`, `enduro-mobile`).
|
||
|
||
## 2. Бизнес-цель
|
||
|
||
Дать оркестратору возможность обслуживать **N проектов одновременно**, не теряя
|
||
текущей функциональности по `enduro-trails` и без миграции исторических данных.
|
||
|
||
Это нужно, чтобы:
|
||
|
||
- запускать пайплайн на самом репо `orchestrator` (dogfooding —
|
||
улучшения оркестратора проходят через тот же пайплайн);
|
||
- начать вести новые проекты той же командой и тем же инструментарием
|
||
(тайлы, мобильное приложение, бэкенды для соседних идей);
|
||
- иметь единую точку наблюдения за разработкой нескольких репо
|
||
(один `/status`, один Telegram-канал, одни логи).
|
||
|
||
## 3. Целевые пользователи и сценарии
|
||
|
||
| Роль | Сценарий | Ожидание |
|
||
|------|----------|----------|
|
||
| Owner (homenet542@gmail.com) | Подключить к оркестратору новый проект `foo` | За один шаг (правка конфига + перезапуск) проект становится известен оркестратору. Никаких code-change'ей в `src/`. |
|
||
| Stakeholder в Plane | Создаёт work item в проекте `Foo` (Plane workspace) | Получает branch `feature/FOO-NNN-slug` в Gitea-репо `foo`, артефакты в `docs/work-items/FOO-NNN/`, анализ запускается автоматически. |
|
||
| Developer (claude-bot) | Анализирует work item, который пришёл из проекта `Foo` | Видит корректный work item ID (`FOO-007`), корректный repo (`foo`), корректную ветку (`feature/FOO-007-...`). Worktree создаётся под нужным репо. |
|
||
| Owner | Смотрит `/status` оркестратора | Видит все активные задачи across all repos, с указанием repo для каждой. |
|
||
| Owner | Хочет временно поставить проект на паузу | Может выключить конкретный проект в конфиге, не трогая остальные. |
|
||
|
||
## 4. Бизнес-требования
|
||
|
||
### BR-1. Реестр проектов
|
||
Оркестратор должен знать список обслуживаемых проектов. Источник истины
|
||
конфигурируется (env / file / иной способ — на усмотрение архитектора).
|
||
Для каждого проекта задаются как минимум:
|
||
- имя Gitea-репо (`repo`),
|
||
- префикс work item ID (`ET`, `ORCH`, `FOO`, ...),
|
||
- идентификаторы Plane (workspace_slug, project_id),
|
||
- маппинг состояний Plane (`backlog`, `todo`, `in_progress`,
|
||
`needs_input`, `in_review`, `blocked`, `done`, `cancelled`) — каждый
|
||
Plane-проект имеет собственные UUID состояний.
|
||
|
||
### BR-2. Маршрутизация Plane-вебхуков по проектам
|
||
При получении вебхука от Plane оркестратор обязан определить, какому
|
||
проекту из реестра принадлежит событие (по `project_id` в payload),
|
||
и работать с настройками этого проекта (Plane state IDs, workspace,
|
||
gitea-репо).
|
||
|
||
### BR-3. Маршрутизация Gitea-вебхуков по репозиториям
|
||
При получении push / PR / status оркестратор должен использовать
|
||
`repository.name` из payload как ключ для поиска проекта в реестре
|
||
вместо `settings.default_repo`.
|
||
|
||
### BR-4. Префикс work item ID — per-project
|
||
Генерация следующего ID должна продолжать существующую нумерацию
|
||
**в пределах своего префикса**: для `enduro-trails` — `ET-016` после
|
||
`ET-015`; для `orchestrator` — `ORCH-001` для первого таска, `ORCH-002`
|
||
далее; ID одного проекта не пересекают и не сдвигают ID другого.
|
||
|
||
### BR-5. Изоляция worktree per (repo, branch)
|
||
Текущая схема `/repos/_wt/<repo>/<safe-branch>` уже репо-aware, но
|
||
оркестратор должен предполагать наличие main-clone'а для каждого репо
|
||
в `/repos/<repo>`. Если main-clone отсутствует — внятная ошибка
|
||
в логах + Telegram (а не падение).
|
||
|
||
### BR-6. Agent prompts и фазы — per-repo
|
||
Agent-промпты (`.openclaw/agents/<agent>.md`), `CLAUDE.md`, `docs/phases/`
|
||
у каждого проекта могут отличаться. Оркестратор не должен «протаскивать»
|
||
артефакты `enduro-trails` в другие репозитории.
|
||
|
||
### BR-7. Обратная совместимость
|
||
Существующий проект `enduro-trails` после миграции продолжает работать
|
||
без потери истории:
|
||
- активные задачи в `tasks` таблице не ломаются;
|
||
- ID `ET-015`, `ET-016`, … продолжают выдаваться;
|
||
- комментарии и состояния в Plane продолжают летать в текущий
|
||
workspace/project.
|
||
|
||
### BR-8. Наблюдаемость
|
||
`/status` (и любые админ-эндпоинты) выводит `repo` для каждой активной
|
||
задачи. Telegram-уведомления и логи также включают `repo`,
|
||
чтобы их можно было разделить per-project.
|
||
|
||
### BR-9. Минимально необходимый рантайм-конфиг
|
||
Подключение нового проекта не требует изменения кода `src/`.
|
||
Только конфиг + наличие main-clone'а репозитория на хосте + перезапуск
|
||
контейнера. Webhook secret-ы (Plane / Gitea) — также per-project.
|
||
|
||
### BR-10. Безопасность
|
||
Каждый Plane-проект может иметь собственный webhook secret;
|
||
оркестратор должен проверять HMAC с правильным секретом для конкретного
|
||
проекта, иначе вебхук отбрасывается с 401.
|
||
|
||
## 5. Out of scope для этой задачи
|
||
|
||
- Параллельная обработка нескольких задач (S-4 уже сделал worktree per
|
||
branch, но in-process очередь задач — отдельный F-2b).
|
||
- Веб-UI для управления проектами.
|
||
- Автоматическое подтягивание main-clone'а нового репо (`git clone`
|
||
выполняется руками или другим инструментом).
|
||
- Изменение pipeline-stage машины (`stages.py`).
|
||
- Изменение модели данных Plane (state-id'ы определяются в Plane,
|
||
оркестратор только подхватывает).
|
||
|
||
## 6. Допущения и ограничения
|
||
|
||
- Все обслуживаемые репозитории живут в одном Gitea-инстансе
|
||
(один `ORCH_GITEA_URL`, один `ORCH_GITEA_TOKEN`, один `owner=admin`).
|
||
Multi-Gitea — не в скоупе.
|
||
- Все Plane-проекты — в одном Plane-инстансе (`ORCH_PLANE_API_URL`),
|
||
но могут быть в разных workspace.
|
||
- Claude CLI бинарник один и тот же (`/opt/claude-code/bin/claude.exe`).
|
||
- Hooks деплоя per-repo не обязаны существовать на этом этапе:
|
||
если у репо нет деплой-стадии — `deploy` помечается `done` без
|
||
смоук-теста (либо проект явно объявляет, что у него нет deploy).
|
||
|
||
## 7. Метрики успеха
|
||
|
||
1. Создание work item'а в Plane-проекте `Orchestrator` приводит к появлению
|
||
ветки `feature/ORCH-NNN-…` в Gitea-репо `orchestrator` и запуску
|
||
analyst-агента в worktree `/repos/_wt/orchestrator/<branch>`.
|
||
2. ID нового таска в `orchestrator` имеет префикс `ORCH-`, а не `ET-`.
|
||
3. Создание work item в `enduro-trails` продолжает работать: ID `ET-016`,
|
||
ветка `feature/ET-016-...`, всё как раньше.
|
||
4. `/status` возвращает поле `repo` для каждой задачи.
|
||
5. Telegram-уведомление содержит `repo` в префиксе сообщения.
|
||
6. Регрессии не наблюдаются на 2 последовательных `ET-NNN` задачах
|
||
после раскатки.
|
||
|
||
## 8. Зависимости и риски (на уровне бизнеса)
|
||
|
||
- Plane state IDs другого проекта надо получить вручную (через Plane UI
|
||
или API) — этим занимается Owner перед подключением.
|
||
- Webhook secret per-project потребует пересоздать webhook'и
|
||
в каждом Plane-проекте и каждом Gitea-репо.
|
||
- Schema `tasks` уже хранит `repo` — миграции данных не требуется.
|
||
|
||
## 9. Связанные документы
|
||
|
||
- 02-trz.md — функциональные/нефункциональные требования (этот пакет).
|
||
- 03-acceptance-criteria.md — критерии приёмки.
|
||
- 04-test-plan.yaml — план тестов.
|
||
- Architecture phase: создаст ADR по способу хранения реестра проектов
|
||
и стратегии маппинга Plane state IDs.
|