docs/PLANNING.md

360 lines
21 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.

# Planning — Team Board
Дата: 2026-02-23
## Принципы
- Каждый эпик = самодостаточный блок, можно релизить независимо
- Порядок = зависимости + приоритет из Architecture Review
- Никаких параллельных эпиков — строго последовательно
- Каждая story имеет чёткие критерии приёмки
## Эпик 1: WebSocket Foundation — Исправить критические баги
Цель: Устранить P0 блокеры из Architecture Review — WS collision и отсутствие task events
Зависимости: нет
### Story 1.1: Исправить WebSocket connection collision
**Как** системный разработчик **я хочу** чтобы множественные подключения одного пользователя не вытесняли друг друга **чтобы** система работала корректно при multiple tabs/reconnect
**Критерии приёмки:**
- [ ] `ConnectionManager.clients` изменён с `dict[str, ConnectedClient]` на `dict[str, list[ConnectedClient]]`
- [ ] Добавлен `sessions: dict[str, ConnectedClient]` с уникальными session_id
- [ ] При подключении создаётся уникальный session_id
- [ ] При отключении удаляется только конкретная сессия
- [ ] Broadcast отправляется всем сессиям пользователя
**Компоненты:** Tracker
**Оценка:** M
### Story 1.2: Добавить broadcast task events
**Как** агент **я хочу** получать уведомления о создании/изменении задач **чтобы** реагировать на новую работу в проекте
**Критерии приёмки:**
- [ ] `POST /api/v1/tasks` вызывает `broadcast_task_event("task.created")`
- [ ] `PATCH /api/v1/tasks/{id}` вызывает `broadcast_task_event("task.updated")`
- [ ] `DELETE /api/v1/tasks/{id}` вызывает `broadcast_task_event("task.deleted")`
- [ ] События содержат полную информацию о задаче
- [ ] WebSocket клиент получает события в формате `{"type": "task.created", "data": task}`
**Компоненты:** Tracker
**Оценка:** M
### Story 1.3: Добавить REST token auth для агентов
**Как** агент **я хочу** аутентифицироваться через токен в REST API **чтобы** делать запросы напрямую к Tracker
**Критерии приёмки:**
- [ ] Middleware `verify_agent_token()` проверяет заголовок `Authorization: Bearer tb-xxxxx`
- [ ] Токен валидируется по таблице Member.token
- [ ] Защищены все эндпоинты кроме `/docs`, `/health`, `/ws`
- [ ] При неверном токене возвращается 401
- [ ] BFF продолжает работать (проксирует с токеном)
**Компоненты:** Tracker
**Оценка:** S
## Эпик 2: Task Operations — Агентские операции с задачами
Цель: Реализовать специальные операции для агентов из PRD
Зависимости: Эпик 1
### Story 2.1: Реализовать take task API
**Как** агент **я хочу** атомарно взять задачу в работу **чтобы** не было race condition с другими агентами
**Критерии приёмки:**
- [ ] `POST /api/v1/tasks/{id}/take` endpoint создан
- [ ] Проверяется что задача в статусе backlog или todo
- [ ] Атомарно устанавливается assignee_slug = текущий агент и status = in_progress
- [ ] При конфликте возвращается 409 Conflict
- [ ] Broadcast task.updated события после успешного взятия
- [ ] BFF проксирует операцию
**Компоненты:** Tracker / BFF
**Оценка:** M
### Story 2.2: Реализовать reject task API
**Как** агент **я хочу** отклонить назначенную мне задачу **чтобы** вернуть её в backlog с объяснением
**Критерии приёмки:**
- [ ] `POST /api/v1/tasks/{id}/reject` с body `{"reason": "string"}`
- [ ] Проверяется что assignee_slug = текущий агент
- [ ] Устанавливается assignee_slug = null, status = backlog
- [ ] Добавляется комментарий-сообщение "Задача отклонена: {reason}"
- [ ] Broadcast task.updated события
- [ ] BFF проксирует операцию
**Компоненты:** Tracker / BFF
**Оценка:** M
### Story 2.3: Реализовать assign task API
**Как** участник **я хочу** назначить задачу другому участнику **чтобы** делегировать работу
**Критерии приёмки:**
- [ ] `POST /api/v1/tasks/{id}/assign` с body `{"assignee_slug": "string"}`
- [ ] Проверяется существование assignee в проекте
- [ ] Устанавливается assignee_slug и status = todo (если был backlog)
- [ ] Broadcast task.updated события
- [ ] BFF проксирует операцию
**Компоненты:** Tracker / BFF
**Оценка:** S
### Story 2.4: Реализовать watch/unwatch task API
**Как** участник **я хочу** подписываться на уведомления по задаче **чтобы** отслеживать её прогресс
**Критерии приёмки:**
- [ ] `POST /api/v1/tasks/{id}/watch` добавляет текущий slug в watchers[]
- [ ] `DELETE /api/v1/tasks/{id}/watch` удаляет slug из watchers[]
- [ ] Дубликаты в watchers игнорируются
- [ ] Broadcast task.updated события при изменении watchers
- [ ] BFF проксирует операции
**Компоненты:** Tracker / BFF
**Оценка:** S
## Эпик 3: WebSocket Events — Правильная фильтрация событий
Цель: Унифицировать фильтрацию событий для всех типов участников
Зависимости: Эпик 2
### Story 3.1: Реализовать project.subscribe для humans
**Как** пользователь веб-клиента **я хочу** подписываться только на события нужных проектов **чтобы** не получать лишний трафик
**Критерии приёмки:**
- [ ] Humans/bridges могут отправлять `project.subscribe` сообщения
- [ ] `connection.subscribed_projects` хранит список подписок
- [ ] По умолчанию подписок нет (не "получать всё")
- [ ] События фильтруются по подпискам для всех типов участников
- [ ] Web Client автоматически подписывается на текущий проект
**Компоненты:** Tracker / Web
**Оценка:** M
### Story 3.2: Унифицировать фильтрацию по listen_mode
**Как** агент с chat_listen="mentions" **я хочу** получать только сообщения где меня упоминают **чтобы** снизить шум в канале
**Критерии приёмки:**
- [ ] Функция `should_receive_event(client, event_type, data)` для всех типов
- [ ] chat_listen="mentions" → только сообщения с mentions[] содержащими агента
- [ ] chat_listen="all" → все сообщения в подписанных проектах
- [ ] task_listen="mentions" → только задачи где агент assignee/reviewer/watcher
- [ ] task_listen="all" → все task события в подписанных проектах
- [ ] Humans используют ту же логику с listen_mode="all" по умолчанию
**Компоненты:** Tracker
**Оценка:** M
### Story 3.3: Исправить on_behalf_of validation
**Как** BFF **я хочу** валидировать on_behalf_of пользователей **чтобы** предотвратить коллизии slug
**Критерии приёмки:**
- [ ] При on_behalf_of проверяется существование Member с таким slug
- [ ] Несуществующие users получают префикс `web-{slug}`
- [ ] Все proxy подключения логируются с уровнем INFO
- [ ] Bridge не может перехватить slug существующего агента
- [ ] Добавлены unit тесты для collision cases
**Компоненты:** BFF
**Оценка:** S
## Эпик 4: Agent Management — UI для управления агентами
Цель: Создать интерфейс для создания и мониторинга агентов
Зависимости: Эпик 3
### Story 4.1: Страница Agent Management
**Как** администратор **я хочу** видеть список всех агентов с их статусами **чтобы** мониторить работу системы
**Критерии приёмки:**
- [ ] Страница `/agents` доступна в навигации
- [ ] Таблица агентов с колонками: name, slug, status, capabilities, last_seen_at
- [ ] Статусы показаны цветами: 🟢 online, 🔴 offline, 🟡 busy
- [ ] Обновление статусов через WebSocket в реальном времени
- [ ] Кнопка "Create Agent" ведёт на форму создания
**Компоненты:** Web
**Оценка:** M
### Story 4.2: Форма создания агента
**Как** администратор **я хочу** создать нового агента и получить его токен **чтобы** подключить к системе
**Критерии приёмки:**
- [ ] Форма с полями: name, slug, capabilities (чекбоксы), chat_listen, task_listen, model
- [ ] Slug валидируется на уникальность
- [ ] При создании генерируется токен формата `tb-{32 random chars}`
- [ ] Токен показывается один раз с предупреждением "Сохраните токен"
- [ ] После создания редирект на `/agents` со списком
- [ ] Токен копируется в clipboard кнопкой
**Компоненты:** Web / BFF / Tracker
**Оценка:** M
### Story 4.3: Agent configuration UI
**Как** администратор **я хочу** редактировать настройки агента **чтобы** корректировать его поведение
**Критерии приёмки:**
- [ ] В таблице агентов кнопка "Edit" открывает модальное окно
- [ ] Поля: name, capabilities, chat_listen, task_listen, model, prompt
- [ ] Slug не редактируется (readonly)
- [ ] Кнопка "Regenerate Token" с подтверждением
- [ ] Изменения сохраняются через PATCH API
- [ ] Обновление конфигурации применяется без перезапуска агента
**Компоненты:** Web / BFF / Tracker
**Оценка:** M
## Эпик 5: Task Steps UI — Интеграция steps в интерфейс
Цель: Показывать прогресс задач через steps UI
Зависимости: Эпик 4
### Story 5.1: Steps в TaskModal
**Как** пользователь **я хочу** видеть этапы задачи в виде чеклиста **чтобы** отслеживать прогресс выполнения
**Критерии приёмки:**
- [ ] Секция Steps между описанием и комментариями в TaskModal
- [ ] Список шагов с чекбоксами и заголовками
- [ ] Прогресс-бар "3 из 7 выполнено" вверху секции
- [ ] Чекбоксы интерактивны — клик отмечает/снимает выполнение
- [ ] Обновления сохраняются через PATCH API
- [ ] Live обновления через WebSocket
**Компоненты:** Web
**Оценка:** M
### Story 5.2: Управление steps в TaskModal
**Как** исполнитель задачи **я хочу** добавлять и удалять этапы **чтобы** планировать свою работу
**Критерии приёмки:**
- [ ] Кнопка "+ Add Step" в секции Steps
- [ ] Инлайн добавление шага с автосохранением
- [ ] Кнопка удаления у каждого шага (только для незавершённых)
- [ ] Drag & drop для изменения порядка шагов
- [ ] Завершённые шаги визуально отличаются (зачёркнутый текст)
**Компоненты:** Web
**Оценка:** S
## Эпик 6: Files & Attachments — Загрузка файлов
Цель: Реализовать upload/download файлов в сообщениях
Зависимости: Эпик 5
### Story 6.1: Upload API для attachments
**Как** пользователь **я хочу** прикреплять файлы к сообщениям **чтобы** делиться документами с командой
**Критерии приёмки:**
- [ ] `POST /api/v1/messages/{id}/attachments` принимает multipart/form-data
- [ ] Файлы сохраняются в `/var/lib/team-board/attachments/{message_id}/`
- [ ] Создаётся Attachment запись в БД с metadata
- [ ] Поддерживаются файлы до 10MB
- [ ] Валидация MIME типов (изображения, документы, код)
- [ ] BFF проксирует загрузку с авторизацией
**Компоненты:** Tracker / BFF
**Оценка:** M
### Story 6.2: Download API для attachments
**Как** пользователь **я хочу** скачивать прикреплённые файлы **чтобы** просматривать их локально
**Критерии приёмки:**
- [ ] `GET /api/v1/attachments/{id}` отдаёт файл с правильными заголовками
- [ ] Content-Type, Content-Length, Content-Disposition установлены
- [ ] Проверка доступа — пользователь должен иметь доступ к сообщению
- [ ] Обслуживание статичных файлов через FastAPI
- [ ] BFF проксирует скачивание с авторизацией
**Компоненты:** Tracker / BFF
**Оценка:** S
### Story 6.3: File preview в UI
**Как** пользователь **я хочу** видеть превью файлов в чате **чтобы** не скачивать их для просмотра
**Критерии приёмки:**
- [ ] Изображения показываются как thumbnail в сообщении
- [ ] Клик на thumbnail открывает полноразмерное изображение
- [ ] Документы показываются как ссылки с иконками типов файлов
- [ ] Код файлы (.js, .py, .md) показываются с syntax highlighting
- [ ] Кнопка скачивания у каждого attachment
**Компоненты:** Web
**Оценка:** M
## Эпик 7: MCP Tools — Инструменты для агентов
Цель: Создать MCP Tools для взаимодействия агентов с системой
Зависимости: Эпик 6
### Story 7.1: Базовые Task Tools
**Как** агент **я хочу** создавать и управлять задачами через MCP **чтобы** автоматизировать workflow
**Критерии приёмки:**
- [ ] `create_task(title, description, project_slug, priority?, labels?)` → task_id
- [ ] `take_task(task_id)` → success/error
- [ ] `update_task(task_id, fields)` → updated task
- [ ] `complete_task(task_id)` → устанавливает status=done
- [ ] `list_tasks(project_slug?, status?, assignee?)` → task list
- [ ] Все tools используют существующий REST API с токен авторизацией
**Компоненты:** Picogent
**Оценка:** M
### Story 7.2: Communication Tools
**Как** агент **я хочу** отправлять сообщения и читать чат **чтобы** участвовать в обсуждениях
**Критерии приёмки:**
- [ ] `send_message(content, chat_id?, task_id?, mentions?)` → message_id
- [ ] `list_messages(chat_id?, task_id?, limit?)` → message list
- [ ] `add_task_comment(task_id, content)` → comment message
- [ ] `mention_user(slug, message)` → автодобавление в mentions[]
- [ ] Все сообщения получают правильный author_slug агента
**Компоненты:** Picogent
**Оценка:** S
### Story 7.3: Project & Member Tools
**Как** агент **я хочу** получать информацию о проектах и участниках **чтобы** понимать контекст работы
**Критерии приёмки:**
- [ ] `list_projects()` → project list с основными полями
- [ ] `get_project(slug)` → детальная информация о проекте
- [ ] `list_members(project_slug?)` → список участников
- [ ] `get_member(slug)` → информация об участнике
- [ ] `watch_task(task_id)` / `unwatch_task(task_id)` → управление подписками
**Компоненты:** Picogent
**Оценка:** S
## Эпик 8: Advanced Features — Дополнительные возможности
Цель: Реализовать отложенные features для полноценной работы
Зависимости: Эпик 7
### Story 8.1: Telegram Bridge Foundation
**Как** пользователь **я хочу** получать уведомления в Telegram **чтобы** не пропускать важные события проекта
**Критерии приёмки:**
- [ ] Bridge агент подключается как member типа "bridge"
- [ ] Принимает все события проектов (listen_mode="all")
- [ ] Фильтрует важные события: task.assigned на меня, mentions в чате
- [ ] Отправляет уведомления в личный чат Telegram
- [ ] Конфигурация через переменные окружения
**Компоненты:** Picogent (отдельный bridge agent)
**Оценка:** L
### Story 8.2: Voice Messages Support
**Как** пользователь **я хочу** отправлять голосовые сообщения **чтобы** быстро комментировать задачи
**Критерии приёмки:**
- [ ] Web Client записывает аудио через MediaRecorder API
- [ ] Upload аудио как attachment с типом audio/*
- [ ] Message.voice_url ссылается на attachment
- [ ] Аудио плеер в UI для воспроизведения
- [ ] Агенты могут транскрибировать voice_url через STT
**Компоненты:** Web / Tracker / Picogent
**Оценка:** L
### Story 8.3: Advanced Task Dependencies
**Как** PM **я хочу** видеть граф зависимостей задач **чтобы** планировать последовательность работ
**Критерии приёмки:**
- [ ] UI для добавления зависимостей в TaskModal (autocomplete других задач)
- [ ] Валидация циклических зависимостей на бэкенде
- [ ] Визуализация зависимостей в виде граф-диаграммы
- [ ] Блокировка взятия задач с незавершёнными зависимостями
- [ ] Автоматическое уведомление при разблокировке задачи
**Компоненты:** Web / Tracker
**Оценка:** L