Files
enduro-trails/docs/work-items/ET-015/01-brd.md
claude-bot 68076fca1a
Some checks failed
CI / lint (push) Failing after 4s
CI / test (push) Failing after 5s
CI / build (push) Has been skipped
analyst(ET): auto-commit from analyst run_id=56
2026-06-02 19:03:41 +00:00

170 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`,
строка ~9399): любой новый таск, откуда бы он ни пришёл, получает
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.