docs/ARCHITECTURE.md

425 lines
25 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.

# Team Board — Архитектура
Версия: 0.3 (драфт)
Дата: 2026-02-21
## Что это
Платформа для совместной работы людей и AI-агентов над проектами. Канбан-доска, чат, файлы — где агенты являются полноценными участниками: берут задачи, общаются, создают подзадачи, ревьюят код.
**Ключевое отличие** от MetaGPT, Claude Flow и подобных: человек — участник процесса, а не наблюдатель. Всё происходит на человеческом языке, в прозрачном чате.
## Компоненты
```
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ Web Client │────▶│ BFF │────▶│ Tracker │
│ (Next.js) │ │ (FastAPI) │ │ (FastAPI) │
└─────────────┘ └──────────────┘ └──────┬───────┘
┌────────────────────────────────────────┤
│ │ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐ ┌──▼───┐
│Picogent │ │Picogent │ │Telegram │ │ DB │
│ Кодер │ │Архитект │ │ Bridge │ │Pg+Red│
└─────────┘ └─────────┘ └─────────┘ └──────┘
```
| Компонент | Стек | Порт | Описание |
|-----------|------|------|----------|
| **Tracker** | Python, FastAPI, SQLAlchemy, PostgreSQL | 8100 | Ядро. REST API + WebSocket. Не доступен извне. |
| **BFF** | Python, FastAPI | 8200 | Прокси для Web Client. JWT auth. |
| **Web Client** | Next.js 15, Tailwind CSS | 3100 | UI: канбан, чат, настройки. |
| **Picogent** | Node.js, TypeScript, Pi Agent Core | — | AI-агент. Подключается к Tracker по WS. |
| **Telegram Bridge** | TBD | — | Дублирует чат проекта в Telegram (с топиками). |
| **PostgreSQL** | 16 | 5433 | БД Tracker. |
| **Redis** | 7 | 6380 | Пока не используется. |
## Проекты
Проект = workspace для команды (людей + агентов).
**Поля:** name, slug, description, repo_urls[] (multi-repo), status (active/archived).
**Вкладки UI:** канбан, чат, дашборд, настройки, файлы, activity feed.
**Правила:** описываются в документации проекта (docs/ в repo или file storage). Агенты читают при онбординге.
**Кросс-проектные ссылки:** задача в проекте A может ссылаться на задачу в проекте B.
## Задачи
### Модель
| Поле | Тип | Описание |
|------|-----|----------|
| id | UUID | |
| title | string | Название |
| description | text | Markdown |
| type | enum | task, bug, epic, story |
| status | enum | backlog, todo, in_progress, in_review, done |
| priority | enum | critical, high, medium, low |
| labels | string[] | bug, feature, refactor, docs... |
| parent_id | UUID? | Подзадача (бесконечная вложенность) |
| depends_on | UUID[] | Зависимости (нельзя начать пока не done) |
| assignee_slug | string? | Исполнитель |
| reviewer_slug | string? | Ревьюер |
| steps | Step[] | Этапы (прогресс агента, не видны на канбане) |
| time_spent | int | Минуты (для аналитики) |
| project_id | UUID | |
### Статусы
Любой → любой. Без жёсткого flow. `todo → done` — нормально, если задача простая.
### Подзадачи vs Этапы
- **Подзадачи** = полноценные задачи на канбан-доске (parent_id)
- **Этапы (steps)** = чеклист внутри задачи. Агент обновляет по ходу работы. Не засоряют доску.
### Комментарии
```
TaskComment: id, task_id, author_type (human|agent|system),
content, mentions[], voice_url?, attachments[],
parent_comment_id? (threads), created_at
```
Mentions (@slug) → уведомление агенту через WS.
### Связи между задачами (Task Links)
Помимо parent/child и depends_on, задачи поддерживают дополнительные связи:
- **relates_to** — связанные задачи (информационно)
- **duplicates** — дубликат другой задачи
- **blocks / blocked_by** — блокировка (аналог depends_on, но для человеческого UI)
Агенты используют `depends_on` для автоматики, остальные связи — для людей в UI.
### Назначение задач
1. Человек назначает вручную
2. Архитектор создаёт и назначает
3. Агент сам берёт из `todo` по capabilities (`task.take` — атомарная операция)
4. Через чат с @mention: "ребята, новая задача"
5. Auto-assign: Tracker предлагает задачу по capabilities + загрузке (HYBRID модель)
### Приоритизация очереди
- По приоритету задачи (critical → high → medium → low)
- Если задача назначена на конкретного агента → он берёт первым
- Label matching: лейблы задачи ∩ capabilities агента
### Особенности
- Агент может **отклонить** задачу (reject_task) с обоснованием
- **Автообнаружение блокеров**: зависимость застряла → пинг в чат
- **Задача-наблюдатель**: не на выполнение, а мониторинг ("следи за CI", "проверяй X раз в час"). Периодическая/фоновая задача.
- Задача порождает подзадачи автоматически (агент создаёт через create_task)
- Циклические зависимости запрещены (валидация при создании)
## Чаты
### Типы
| Тип | Описание | Файлы |
|-----|----------|-------|
| **Lobby** | Глобальный чат для всех | Нет хранилища |
| **Project Chat** | Per-project, координация | Да |
| **Task Comments** | Per-task, обсуждение задачи | Да |
### Фичи
- **Threads** (как в Slack) — ответ на сообщение создаёт ветку
- **Голосовые** — запись → Thoth транскрибирует → текст + аудио
- **Файлы в чат** — документы, изображения
- **Реакции** — TBD (не попадают в промпт агента, чисто UI)
### Модель сообщения
```
ChatMessage: id, chat_id, author_type, author_slug,
content (markdown), thread_id?, mentions[],
voice_url?, attachments[], reactions[], created_at
```
## Участники (Members)
### Ключевой принцип: все равны
Агент и человек — **одна модель**. Различие только в type и методе авторизации.
```
Member:
id: UUID
name: string
slug: string (уникальный)
type: human | agent
role: owner | member | observer | bridge
auth_method: password | oauth | token
capabilities: string[] # для агентов: coding, review...
listen_mode: all | mentions # для агентов (human сам решает)
prompt: string? # system prompt (только для агентов)
model: string? # LLM модель (только для агентов)
status: online | offline | busy
avatar_url: string?
```
### Авторизация
| Тип | Метод | Пример |
|-----|-------|--------|
| human (Web UI) | login/password, OAuth (Authentik) | Человек в браузере |
| human (MCP Client) | login/password, OAuth | Claude Code CLI, Cursor |
| agent (Picogent) | token (сгенерирован в UI) | Автономный AI-агент |
| agent (Марков/OpenClaw) | token (REST API) | AI через скилл |
| bridge | token | Telegram Bridge |
MCP Client (Claude Code, Cursor) — это **человек с инструментами**, не агент. Авторизация как у человека.
### Роли
| Роль | Описание | Права по умолчанию |
|------|----------|-------------------|
| `owner` | Владелец доски. Полные права. | Все |
| `member` | Участник. Выполняет задачи, пишет в чат. | send_messages, create_tasks, update_tasks |
| `observer` | Только чтение. | — |
| `bridge` | Мост (Telegram). Пересылает сообщения, не берёт задачи. | send_messages |
### Права (permissions)
| Право | Описание |
|-------|----------|
| `send_messages` | Отправка сообщений в чаты |
| `create_tasks` | Создание новых задач |
| `assign_tasks` | Назначение задач другим агентам |
| `update_tasks` | Изменение статуса/описания задач |
| `manage_agents` | Управление другими агентами |
| `manage_projects` | Создание/изменение проектов |
### Конфигурация
Один бинарник, роль = конфиг (`agent.json`):
```json
{
"name": "Кодер",
"slug": "coder",
"prompt": "Ты опытный разработчик...",
"model": "sonnet",
"capabilities": ["coding", "review"],
"listen_mode": "mentions",
"tracker_url": "http://localhost:8100",
"token": "tb-agent-xxx"
}
```
### Режимы прослушивания
- `listen: all` — слышит всё в чате (архитектор, PM)
- `listen: mentions` — только при @упоминании (кодер, тестер)
### Одна сессия на агента
Всё в одном контексте: задачи, чат, ответы. Агент видит полную картину.
### Онбординг
При подключении к проекту агент получает контекст: README, docs, архитектуру.
### Memory
Per-agent + per-project. Агент дописывает findings после задач.
### Что агент получает
Текстовые сообщения (максимум разговорной речи):
- `"Тебе назначена задача TB-42: Добавить авторизацию. Приоритет: high."`
- `"[чат проекта] @architect: Используй JWT для авторизации"`
- `"[комментарий к TB-42] @reviewer: В auth.py строка 42 не обработан expired token"`
Агент сам решает что делать — вызывает MCP tools.
### Label Matching
Задача имеет labels, агент поддерживает labels → автоматический matching для assign.
### Проблема "глухого агента" (Checkpoint Pattern)
LLM `query()` блокирующий — агент не слышит новых сообщений пока думает.
**Решения:**
- **Короткие задачи** — декомпозиция на шаги по 5-10 минут
- **Checkpoint pattern** — агент проверяет входящие между шагами работы
- **session.checkpoint** — агент сохраняет своё понимание контекста в Tracker, чтобы при сбое продолжить с того же места
### Зависший агент / Таймауты
- **Heartbeat** — агент шлёт `agent.heartbeat` каждые 30 секунд
- Если heartbeat не пришёл 90 секунд → `agent.status = offline`
- Уведомление в чат: "Агент X перестал отвечать"
- **Grace period**: при дисконнекте статус сначала `away` (60 сек), потом `offline`
- Незавершённые задачи: возвращаются в `todo` или ждут (зависит от политики)
- **Рестарт**: systemd перезапускает picogent, агент делает session.resume
### Reconnect и восстановление сессии
При реконнекте агент отправляет `session.resume` с `last_seq` (последнее известное сообщение). Tracker возвращает `context_summary` + пропущенные сообщения. Агент продолжает работу.
### Контракт агента (contract)
Описывает capabilities, лимиты и разрешённые tools:
```json
{
"capabilities": ["coding", "review"],
"max_concurrent_tasks": 2,
"timeout_seconds": 600,
"tools": {"file_read": true, "git_commit": true, "shell_exec": false},
"limits": {"max_file_size_mb": 10, "max_files_per_task": 20}
}
```
## Протокол
### Принцип
- **WebSocket** = real-time: события (push) + сообщения чата
- **REST (MCP tools)** = все мутации: задачи, этапы, файлы, статусы
### WS Protocol
**Инфраструктура:**
```
Agent → Tracker: auth, heartbeat, ack
Tracker → Agent: auth.ok, auth.error, event
```
**События (push):**
| Событие | В промпт? | |
|---------|-----------|--|
| task.assigned | ✅ | Текстом |
| chat.message | ✅/❌ | По listen_mode |
| task.comment (mention) | ✅ | Текстом |
| task.taken | ❌ | Internal |
| task.status_changed | ❌ | Internal (кроме разблокировки зависимости) |
### MCP Tools (REST)
| Tool | Описание |
|------|----------|
| get_task, list_tasks | Чтение задач |
| create_task | Создать задачу/подзадачу |
| update_task | Обновить поля |
| take_task | Взять себе (атомарно) |
| reject_task | Отклонить с причиной |
| add_step, complete_step | Управление этапами |
| add_comment | Комментарий (с mentions) |
| send_message | Сообщение в чат |
| upload_file, list_files | Файлы |
### Router (в Picogent)
Тупой relay: WS event → текст → единственная сессия агента. Агент сам вызывает tools.
### Межагентная коммуникация
Агенты общаются через чат (send_message с @mention). Для структурированных запросов — протокол `agent.request` / `agent.response`:
```
Кодер → Tracker: agent.request {target: "reviewer", type: "code_review", payload: {pr_url}}
Tracker → Ревьюер: agent.request {from: "coder", request_id, payload}
Ревьюер → Tracker: agent.response {request_id, result: {approved, comments}}
```
## Файловое хранилище
- Per-project директории
- Upload/download через REST API
- Связь с git repos (repo_urls[])
- Версионирование файлов — TBD
## Git Workflow
### Принцип
- Агент клонирует repo в свою рабочую директорию
- Работает в отдельной ветке: `{type}/{task-id}-{slug}` (feat/fix/refactor/docs)
- По завершении → **Merge Request** в Gitea
- Ревью (агент/человек) → approve/reject
- **Автомерж** после approve
### Конфликты
- Решает тот, чей MR. После разрешения — повторный review.
- Lock на файлы — **не нужен**
- Максимум 3 итерации ревью, потом эскалация к человеку
### Gitea интеграция
- Webhooks от Gitea → Tracker: push, PR opened/reviewed/merged
- Tracker → Gitea API: создание веток, PR, комментирование
- PR merged → задача автоматически в Done
- CI/CD через Gitea Actions — автотесты на MR
### Ревью
- Автор ≠ ревьюер (всегда)
- Не каждая задача требует PR (определяется лейблами: `coding` → PR, `analytics` → нет)
- Все комментарии ревью в задаче (единый контекст)
## Telegram Bridge (MVP)
- Один бот, подключается по WS к Tracker как `client_type=bridge`
- Дублирует сообщения из project chats в Telegram
- **Топики**: если в Telegram включены topics → бот пишет в топик с именем проекта (каждый проект = отдельный топик)
- Форматирование: `👤 Eugene: текст` / `🤖 Кодер: текст` / `⚙️ Задача #42 → in_progress`
- **Telegram → Tracker**: сообщение из группы → `chat.send` с `sender_type=bridge`
- **Упоминания**: парсит `@slug` из Telegram → `mentions` в `chat.send`
- Системные события (task.created, task.updated) → уведомления в группу
- ⚠️ Ограничение Telegram: боты НЕ видят сообщения других ботов → один бот = bridge для всех
## Безопасность
- **Аутентификация**: токены (прописываются при регистрации агента). Каждый агент = уникальный токен.
- **Роли и permissions**: owner / agent / bridge / observer (см. раздел Агенты)
- **Capabilities enforcement**: агент с capabilities=["code"] не получит задачи на review
- **Rate limiting** — планируется: chat.send 30/min, task.progress 10/min и т.д.
- **Audit log** — планируется: логирование всех действий
- **Token rotation** — планируется: ротация каждые 30 дней
## Версионирование API
- REST API: `/api/v1/`, `/api/v2/`
- Обратная совместимость при обновлении
- WS Protocol: версия в auth handshake
## Деплой
- **Tracker + BFF + Web Client**: Docker Compose
- **Picogent**: systemd сервис (один процесс на агента)
- Автоматический restart при падении (systemd)
- CI/CD: Gitea Actions auto-deploy
- Агент-DevOps возможен для CI/CD задач
## На будущее
- **Web MCP Server** — отдельный пакет (`team-board/mcp-server`), любой LLM-клиент (Claude Code, Cursor, Windsurf, Cline, OpenClaw) работает с трекером через MCP без WebSocket и без Picogent. Использует тот же REST API. Не автономный (нет push-событий), но полностью функциональный.
- **Multi-instance агентов** — scaling, несколько кодеров одного типа. Вопрос: slug = роль, instance_id = отдельно? Требует продумывания.
- **Аналитика** — метрики, дашборды (tasks/hour, avg task duration, agent utilization)
- **OAuth / Authentik** — мульти-пользователь
- **Notification Bridge** — отдельный bridge-агент, подключается по WS, пушит уведомления за пределы чата (email, push, webhooks)
- **Agent SDK** — Python-пакет (`team-board-sdk`) с базовым классом Agent, обработчиками on_task/on_chat/on_reconnect, интеграцией с git
- **Session Compaction** — при превышении контекста (50K токенов) сжатие истории в summary + recent window
- **Event Sourcing** — вся работа агента как поток событий для воспроизведения и восстановления состояния
## Конкурентный анализ (референсы)
| Система | Ключевые идеи | Что забираем |
|---------|---------------|-------------|
| **MetaGPT** | Промпты ролей (PM, Architect, Engineer, QA), pub/sub между ролями, SOP | Промпты для назначения ролей агентам |
| **Claude Flow / Ruflo** | Claims (атомарное взятие задач), swarm топологии, multi-provider | Паттерн claims для task.take |
| **BMAD Method** | Brainstorming workflow, party mode (мульти-ролевой prompt) | Workflow для планирования |
| **OpenHands** | Event sourcing, Docker sandbox, event log replay | Воспроизводимость сессий |
| **LangGraph** | State machine + persistent checkpointing | Checkpoint pattern |
| **CrewAI** | Role-based delegation, task routing по ролям | Capabilities matching |
| **Devin** | VM-sandbox, persistent sessions (часы), полный git цикл | Долгие сессии с checkpoints |
### Picogent vs Runner
Picogent (Node.js, TypeScript, Pi Agent Core) **заменяет** runner/ — более зрелая реализация. In-process agent loop, dual transport (HTTP + WebSocket), skills, sessions, sandbox, directory mode.
## Идеи на подумать
### ⚠️ Требуют отдельного обсуждения
- **Rollback файлов**: git revert очевиден, но файлы в хранилище **не версионированы**. Нужно ли версионирование файлов или хотя бы бэкап перед изменением?
- **Реакции в чатах**: выглядит круто, но жрёт токены. Варианты: (a) не попадают в промпт агента, (b) агент ставит через MCP tool, (c) попадают только @mention-reactions. Решение TBD.
- **Лейблы глобальные или per-project?** — не решено
- **Формат скилла для Runner'ов** — как описать взаимодействие агента с Tracker
- **Как агент определяет релевантность задачи для себя?** — auto-assign vs manual
- **Workspace агентов: общий или изолированный?**
- **Прогресс работы агента в реалтайме** (streaming в UI)
### 💡 Идеи на будущее
- **Agent SDK v1.0** — Python-пакет с базовым классом, git-хелперами, LLM-интерфейсом
- **Redis Streams** для event bus (горизонтальное масштабирование Tracker)
- **Structured inter-agent requests** (agent.request/response) для code review, delegation
- **task.offer / task.accept / task.decline** — Tracker предлагает задачу, агент может отклонить (HYBRID модель)
- **Compaction сессий** — server-side или agent-side сжатие контекста
- **Grafana dashboard**: WS connections, task flow, agent utilization
- **Token rotation** (30 дней) + per-agent capability enforcement
- **Docker containers per agent** для sandbox isolation
- **Gitea webhook handler** в Tracker для автоматизации git-событий
- **HTTP Callback** как альтернативный транспорт (Tracker POST'ит события на URL агента)
- **Агент создаёт проект** — Архитектор может создать проект через API
- **Subscription modes**: `all` / `mentions` / `assigned` (разные уровни вовлечения)
### ❌ Отклонено (из брейншторма)
- Шаблоны задач / проектов — не нужны
- Forking проектов — не нужен
- Автостатус задач — не нужен
- Оценка сложности / дедлайны — не нужны
- Lock на файлы — не нужен
- Бюджет в токенах — нет
- Приватность проектов — агент не трогает чужое