12 KiB
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. Это видно по нескольким местам:
ORCH_DEFAULT_REPO=enduro-trails— единственный fallback, который используется почти везде вwebhooks/plane.py,webhooks/gitea.py,agents/launcher.py.- Префикс work item ID жёстко
ET-(get_next_work_item_idвdb.py, строка ~93–99): любой новый таск, откуда бы он ни пришёл, получает ID видаET-NNN. - Plane-настройки одиночные:
ORCH_PLANE_WORKSPACE_SLUG,ORCH_PLANE_PROJECT_ID, словарьPLANE_STATESсо state-id'ами конкретного проектаenduro-trails. Webhooks от другого Plane-проекта будут обработаны, но patch'и состояний и комментарии полетят в чужой проект. - Документация (
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. Метрики успеха
- Создание work item'а в Plane-проекте
Orchestratorприводит к появлению веткиfeature/ORCH-NNN-…в Gitea-репоorchestratorи запуску analyst-агента в worktree/repos/_wt/orchestrator/<branch>. - ID нового таска в
orchestratorимеет префиксORCH-, а неET-. - Создание work item в
enduro-trailsпродолжает работать: IDET-016, веткаfeature/ET-016-..., всё как раньше. /statusвозвращает полеrepoдля каждой задачи.- Telegram-уведомление содержит
repoв префиксе сообщения. - Регрессии не наблюдаются на 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.