docs/archive/IDEAS.md

26 KiB
Raw Blame History

Team Board — Идеи и концепция

Суть проекта

Team Board — платформа для управления командой AI-агентов, работающих над проектами.

Ключевая идея: Несколько AI-агентов работают как команда разработчиков. Человек видит всё: задачи, код, переписку. Полная прозрачность.


Проблема, которую решаем

Один универсальный AI-ассистент:

  • Контекст переполняется при разных задачах
  • Сложно параллельно вести несколько направлений
  • Нет специализации — один промпт на всё

Решение: Команда специализированных агентов, каждый со своей ролью и контекстом.


Архитектура: Tracker-Centric

Принцип

Tracker = центральный сервис. Всё остальное — клиенты.

┌─────────────────────────────────────────────────────┐
│              WEB CLIENT                              │
│  ┌───────────┐     ┌────────────┐                   │
│  │  Next.js  │ ←→  │  BFF       │  (свой бэкенд)   │
│  │  фронтенд │     │  Python    │                   │
│  └───────────┘     │  + Authentik│                   │
│                    └─────┬──────┘                    │
└──────────────────────────┼──────────────────────────┘
                           │ ws (внутренняя сеть)
              ┌────────────▼────────────┐
              │        TRACKER          │
              │    (внутренний сервис)   │
              │    НЕ выставлен наружу   │
              │                         │
              │  - проекты              │
              │  - доски (канбан)       │
              │  - задачи + подзадачи   │
              │  - чаты                 │
              │  - события              │
              │  - БД (PostgreSQL)      │
              └────────────┬────────────┘
                           │ ws
         ┌─────────────────┼─────────────────┐
         ▼                 ▼                 ▼
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│  Агент 1     │  │  Агент 2     │  │  Агент N     │
│  (Claude)    │  │  (Codex)     │  │  (Gemini)    │
│  отд. сервис │  │  отд. сервис │  │  отд. сервис │
└──────────────┘  └──────────────┘  └──────────────┘

Компоненты

Компонент Описание
Tracker Ядро: проекты, задачи, чаты, события. Внутренний, WebSocket сервер. Роутинг событий агентам
Web Client Next.js + BFF (Python). Авторизация через Authentik. Единственное что торчит наружу
Агенты Независимые приложения (любой язык). Подключаются к Tracker по WebSocket

Репозитории

team-board/
├── tracker/      — ядро (Python, WebSocket, PostgreSQL)
├── web-client/   — Next.js + BFF
└── docs/         — документация

Агенты — отдельные репозитории (шаблон + конкретные).


Канбан-доска

Колонки

┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Backlog  │ │   TODO   │ │ In Prog  │ │  Review  │ │   Done   │
├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤
│ [draft]  │ │ [ready]  │ │ [active] │ │ [review] │ │[complete]│
│ [draft]  │ │ [ready]  │ │          │ │          │ │[complete]│
│          │ │          │ │          │ │          │ │          │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘

Статусы задач

Статус Описание
draft Черновик. Можно обсуждать, но не выполнять
ready Готова к выполнению. Перенос из Backlog → TODO автоматически ставит этот статус
in_progress Агент взял в работу
review На ревью у другого агента
completed Выполнена
blocked Заблокирована зависимостью

Жизненный цикл задачи

1. Человек создаёт задачу → draft (Backlog)
2. Обсуждение в чате проекта
3. Человек перетаскивает в TODO → статус меняется на ready
4. Агент берёт задачу → in_progress
5. Агент завершает → review
6. Ревьюер проверяет → completed / возврат в in_progress

Задачи

Структура задачи

Задача:
  id: uuid
  проект: project_id
  название: "Реализовать API авторизации"
  описание: "Markdown текст с деталями"
  статус: draft | ready | in_progress | review | completed | blocked
  
  # Лейблы (как в Jira — произвольные, создаются в трекере)
  лейблы: ["coding", "api", "backend", "urgent"]
  
  # PR (вручную или по лейблу)
  требует_pr: true | false
  
  # Назначение
  назначен: agent_id (или null)
  
  # Вложенные файлы
  файлы:
    - name: "schema.sql"
      type: "text/sql"
      content: "..."
    - name: "mockup.png"
      type: "image/png"
      url: "/files/task-123/mockup.png"
  
  # Подзадачи (неограниченная вложенность)
  подзадачи:
    - название: "Написать модели"
      назначен: agent-coder
      статус: completed
    - название: "Code review"
      назначен: agent-reviewer
      статус: in_progress
  
  # Зависимости
  зависит_от: [task_id_1, task_id_2]
  блокирует: [task_id_3]
  
  # Мета
  приоритет: low | medium | high | critical
  теги: ["api", "auth"]
  создано: timestamp
  обновлено: timestamp

Зависимости задач

Task A ──depends_on──→ Task B
         │
         └─ Task A НЕ может быть взята пока Task B не completed

Пример:
  "Написать тесты" зависит от "Написать код"
  "Деплой" зависит от "Тесты пройдены"

Правила:

  • Задача со статусом blocked не может быть взята агентом
  • Когда зависимость завершена → автоматически разблокировать
  • Циклические зависимости запрещены (валидация при создании)
  • В UI: визуальная связь между задачами (стрелки)

Приложенные файлы

  • К задаче можно прикрепить файлы (код, изображения, документы)
  • Агент может добавлять файлы к задаче (результаты работы)
  • Файлы хранятся на диске, метаданные в БД
  • Превью для изображений и кода в UI

Чаты

Три уровня

1. Лобби (общий чат)

Отдельная сущность, не привязан к проекту:

  • Обсуждение идей с агентами
  • Аналитика, brainstorm
  • Агент может создавать файлы, заметки
  • Место для обсуждения до создания проекта

2. Чат проекта

У каждого проекта свой чат:

  • Обсуждение задач
  • Системные уведомления (задача создана, завершена, etc.)
  • Агенты видят только чаты своих проектов

3. Комментарии задачи

Внутри каждой задачи:

  • Обсуждение деталей
  • Код ревью
  • Результаты подзадач

Агенты

Принцип

Агент = независимое приложение. Написано на чём угодно (Python, Go, Rust, JS — без разницы). Подключается к Tracker по WebSocket. Может быть даже человек с WebSocket-клиентом.

Tracker не знает и не заботится, что внутри агента — нейросеть, скрипт или человек.

Структура агента

Агент:
  id: uuid
  имя: "Кодер"
  slug: "coder"
  
  # Capabilities — что умеет этот агент
  capabilities: ["coding", "backend", "testing"]
  
  # Подписка
  подписка:
    режим: assigned    # all | mentions | assigned
    проекты: ["*"]     # или конкретные
  
  # Ограничения
  макс_параллельных: 2
  таймаут: 600  # секунд
  
  # Статус (управляется Tracker)
  status: online | offline | busy
  last_heartbeat: timestamp

Лейблы

Произвольные метки, создаются в трекере (как в Jira):

CREATE TABLE labels (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT UNIQUE NOT NULL,   -- "coding", "design", "urgent"
    color TEXT,                  -- "#ff0000"
    created_at TIMESTAMPTZ DEFAULT NOW()
);

Примеры: coding, design, analytics, testing, docs, backend, frontend, urgent, bug

Связка: лейблы задач ↔ capabilities агентов

Задача с лейблом "coding" → только агенты с capability "coding"
Задача с лейблом "design" → только агенты с capability "design"

Агент-дизайнер НЕ возьмёт задачу с лейблом codingу него нет такой capability.

Подписка на события

Режим Агент получает
all Все события в подписанных проектах
mentions Только когда @упомянут
assigned Назначенные задачи + mentions

WebSocket протокол

Подключение и Init Handshake

При подключении агент проходит аутентификацию и получает начальный контекст:

1. Агент подключается: ws://tracker:8100/ws
2. Агент → Tracker: auth
   {
     "type": "auth",
     "token": "agent-token-xxx"
   }

3. Tracker → Агент: auth.ok + init (начальный контекст)
   {
     "type": "auth.ok",
     "agent": {
       "id": "uuid",
       "name": "Кодер",
       "capabilities": ["coding", "backend"]
     },
     "init": {
       "projects": [
         {"id": "uuid", "name": "Team Board", "slug": "team-board"}
       ],
       "assigned_tasks": [
         {"id": "uuid", "title": "...", "status": "in_progress", "project_id": "uuid", "labels": ["coding"]}
       ],
       "pending_tasks": [
         {"id": "uuid", "title": "...", "status": "ready", "project_id": "uuid", "labels": ["coding"]}
       ]
     }
   }

4. При ошибке:
   {
     "type": "auth.error",
     "message": "Invalid token"
   }
   → соединение закрывается

init содержит:

  • projects — проекты, в которых участвует агент
  • assigned_tasks — задачи, назначенные на этого агента (in_progress, review)
  • pending_tasks — задачи, подходящие по capabilities и готовые к взятию (ready)

Роутинг событий (Tracker → Агент)

Tracker фильтрует события по трём критериям:

1. Capabilities — лейблы задачи ∩ capabilities агента

  • Задача с лейблом coding → только агентам с capability coding
  • Нет совпадения → событие не отправляется

2. Подписка агента (subscription mode)

  • assigned → только свои задачи + @mentions
  • mentions → @mentions в чатах и комментариях
  • all → все события (фильтруются по capabilities)

3. Чаты — отдельная логика:

  • Чат задачи → assignee + участники обсуждения
  • Чат проекта → все агенты проекта (без фильтра по capabilities — обсуждение для всех)
  • Лобби → все подключённые агенты

Трекер → Клиент (события)

task.created    — задача создана (с учётом роутинга)
task.updated    — задача обновлена (статус, описание, лейблы)
task.ready      — задача готова к выполнению
task.assigned   — задача назначена агенту
task.blocked    — задача заблокирована зависимостью
task.unblocked  — зависимость выполнена, задача разблокирована
chat.message    — новое сообщение в чате (с учётом роутинга)
agent.status    — статус агента изменился (online/offline/busy)
file.attached   — файл прикреплён к задаче

Клиент → Трекер (команды)

auth            — аутентификация (первое сообщение)
task.take       — агент берёт задачу
task.complete   — агент завершил задачу
task.update     — агент обновляет задачу (статус, описание)
task.comment    — комментарий к задаче
task.attach     — прикрепить файл
chat.send       — отправить сообщение в чат
agent.heartbeat — пульс (каждые 30 сек)

Heartbeat

Агент → Tracker (каждые 30 сек):
{
  "type": "agent.heartbeat",
  "status": "idle" | "busy",
  "current_tasks": ["task-uuid-1"]
}

Если heartbeat не пришёл 90 секунд → agent.status = offline

Ревью и PR

Не каждая задача = PR

PR нужен когда задача связана с кодом. Определяется вручную или по лейблам:

  • Лейбл coding / testingтребует_pr = true (по умолчанию)
  • Лейбл design / analyticsтребует_pr = false
  • Можно переопределить вручную

Флоу ревью (для задач с PR)

1. Агент работает → коммитит в feature branch
2. Создаёт PR в Gitea
3. Сдвигает задачу в Review
4. Трекер назначает ревьюера (другой агент, НЕ автор)
5. Ревьюер смотрит PR, пишет комментарии В ЗАДАЧЕ
6. Ок → Approve → Done, PR мержится
7. Не ок → замечания → обратно In Progress → автор исправляет

Флоу ревью (для задач без PR)

1. Агент работает → прикрепляет результат (файл/отчёт) к задаче
2. Сдвигает в Review
3. Ревьюер проверяет результат
4. Ок → Done
5. Не ок → замечания → обратно In Progress

Правила ревью

  • Автор ≠ ревьюер (всегда)
  • Максимум 3 итерации — потом эскалация к человеку
  • Все комментарии в задаче (единый контекст)
  • Чат проекта = лог событий (всё видно)

Итерации ревью

review_history:
  - iteration: 1
    reviewer: analyst
    status: changes_requested
    comments: ["Нужна валидация", "Нет тестов"]
  - iteration: 2
    reviewer: analyst
    status: approved

Workflow: от идеи до деплоя

Фаза 1: Идея → Проект

  1. Человек открывает Лобби
  2. Обсуждает идею с агентом-аналитиком
  3. Создаёт проект
  4. Агент формирует BRIEF.md, REQUIREMENTS.md

Фаза 2: Декомпозиция → Задачи

  1. На основе требований создаются задачи (черновики в Backlog)
  2. Расставляются зависимости
  3. Прикрепляются файлы (макеты, схемы)
  4. Обсуждение в чате проекта
  5. Готовые задачи переносятся в TODO

Фаза 3: Выполнение

  1. Задача в TODO → агент берёт → In Progress
  2. Агент работает, коммитит, прикрепляет файлы
  3. Создаёт подзадачу "Ревью" → другому агенту
  4. Итерации до готовности
  5. Задача → Done

Фаза 4: Ревью и деплой

  1. Автоматические проверки (CI/CD)
  2. Ревью агентом или человеком
  3. Деплой

Инфраструктура (уже есть)

Сервис Описание
PostgreSQL База данных
Thoth STT/TTS (голос↔текст)
Authentik SSO для веб-интерфейса
Nginx + certbot Домены и SSL
Gitea Git хостинг
OpenClaw (Марков) Главный агент с инструментами
Redis Очереди и pub/sub

База данных (ключевые таблицы)

-- Агенты (независимые приложения)
CREATE TABLE agents (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT NOT NULL,
    slug TEXT UNIQUE NOT NULL,
    token TEXT UNIQUE NOT NULL,             -- токен для WebSocket auth
    capabilities TEXT[] NOT NULL DEFAULT '{}', -- ["coding", "analytics", ...]
    subscription_mode TEXT DEFAULT 'assigned', -- all, mentions, assigned
    max_concurrent INT DEFAULT 1,
    timeout_seconds INT DEFAULT 600,
    status TEXT DEFAULT 'offline',          -- online, offline, busy
    last_heartbeat TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Задачи
CREATE TABLE tasks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    project_id UUID REFERENCES projects(id),
    parent_id UUID REFERENCES tasks(id),  -- подзадачи
    title TEXT NOT NULL,
    description TEXT,
    status TEXT DEFAULT 'draft',
    -- лейблы через связующую таблицу task_labels
    requires_pr BOOLEAN DEFAULT FALSE,
    assigned_agent_id UUID REFERENCES agents(id),
    priority TEXT DEFAULT 'medium',
    pr_url TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Зависимости задач
CREATE TABLE task_dependencies (
    task_id UUID REFERENCES tasks(id) ON DELETE CASCADE,
    depends_on_id UUID REFERENCES tasks(id) ON DELETE CASCADE,
    PRIMARY KEY (task_id, depends_on_id)
);

-- Лейблы
CREATE TABLE labels (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT UNIQUE NOT NULL,
    color TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Связка задач и лейблов
CREATE TABLE task_labels (
    task_id UUID REFERENCES tasks(id) ON DELETE CASCADE,
    label_id UUID REFERENCES labels(id) ON DELETE CASCADE,
    PRIMARY KEY (task_id, label_id)
);

-- Файлы задач
CREATE TABLE task_files (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    task_id UUID REFERENCES tasks(id) ON DELETE CASCADE,
    filename TEXT NOT NULL,
    mime_type TEXT,
    file_path TEXT NOT NULL,
    uploaded_by UUID,  -- agent_id или null (человек)
    created_at TIMESTAMPTZ DEFAULT NOW()
);

Управление агентами (Agent Manager)

Принцип

Агент = независимое приложение. Написано на чём угодно. Подключается к Tracker по WebSocket. Tracker не управляет запуском — агент сам стартует и подключается.

AgentManager (в Tracker)

Tracker отслеживает подключённых агентов:

Реестр агентов:
  - id: uuid
    name: "Кодер"
    status: online | offline | busy
    capabilities: ["coding", "backend"]
    last_heartbeat: timestamp
    current_tasks: [task_id]

Функции AgentManager:

  1. Регистрация — агент подключился → auth → попал в реестр
  2. Мониторинг — следит за heartbeat, помечает offline если пропал
  3. Назначение задач — матчит задачу → подходящего агента по capabilities + загрузке
  4. Роутинг событий — фильтрация по capabilities + подписке + чатам

Открытые вопросы

  1. Workspace для агентов — общий или изолированный?
  2. Прогресс работы агента в реалтайме?
  3. Биллинг/учёт использования API?

Приоритеты реализации

Сделано

  1. Tracker: REST API (проекты, задачи, агенты, лейблы)
  2. Tracker: базовый WebSocket (connection manager, heartbeat)
  3. Tracker: Docker Compose (postgres + redis + tracker)
  4. Web Client: канбан-доска с drag-and-drop
  5. Web Client: BFF с JWT авторизацией
  6. CI/CD: Gitea Actions auto-deploy

В работе 🔧

  1. Web Client: детальный вид задачи (описание, комменты, assignee)
  2. Tracker: WebSocket протокол v2 (init handshake, роутинг событий)

Следующее 📋

  1. Tracker: чаты (лобби + проект + задача)
  2. Tracker: файлы в задачах
  3. Web Client: чат
  4. Web Client: управление агентами
  5. Первый агент (OpenClaw → Tracker)
  6. Web Client: Authentik OAuth

Документ для обсуждения и аналитики. Обновляется по мере развития идей.

RBAC — Система прав (TODO)

Идея

Гранулярные права для участников проекта и агентов.

Участники проекта

  • Owner — создатель проекта, полный доступ (всегда по умолчанию)
  • Member — стандартный участник, полный доступ (текущее поведение)
  • Viewer — только чтение (уже решено ранее)
  • Custom roles — настраиваемые роли с набором permissions

Permissions (идеи)

  • tasks.create — создание задач
  • tasks.edit — редактирование задач
  • tasks.delete — удаление задач
  • tasks.change_status — смена статуса
  • tasks.assign — назначение исполнителя
  • files.upload — загрузка файлов
  • files.delete — удаление файлов
  • chat.send — отправка сообщений
  • project.settings — доступ к настройкам проекта
  • members.manage — добавление/удаление участников

Права для агентов

  • Ограничение действий через ту же систему permissions
  • Например: агент может менять статус, но не может удалять задачи
  • Настраивается в AgentConfig или через роли

Реализация (потом)

  • Таблица roles (project-scoped)
  • Таблица role_permissions (role_id → permission)
  • project_members.role_id вместо текущего role: str
  • Middleware/dependency проверяет permissions на каждом endpoint