agent-ecosystem/docs/team-management
iliya 2eac440fe2 fix(team): disable teammate DM relay through lead, read user.json directly
Teammates are independent Claude Code processes that read their own inbox
files via fs.watch. Relaying DMs through the lead caused three bugs:
lead responding instead of the teammate, duplicate messages from relay
loops, and teammates not responding to user due to conflicting prompts.

- Disable relayMemberInboxMessages for teammate DMs (teams.ts, index.ts)
- Add SendMessage(to="user") filter in captureSendMessages as safety net
- Generate deterministic messageId for inbox entries lacking one (sha256)
- Wrap notification instructions in agent block, italic task subject
- Style system comments in task view with blue background, hide avatar
- Update CLAUDE.md, research docs, and code comments with architecture
2026-03-23 12:57:16 +02:00
..
implementation.md feat(team-management): implement initial Team Management feature with Kanban support 2026-02-17 21:10:15 +02:00
kanban-design.md feat(team-management): implement initial Team Management feature with Kanban support 2026-02-17 21:10:15 +02:00
README.md feat: use agent teams 2026-02-22 23:36:11 +02:00
research-cli-orchestration.md feat(team-managment): stable MVP 2026-02-21 09:47:24 +02:00
research-inbox.md fix(team): disable teammate DM relay through lead, read user.json directly 2026-03-23 12:57:16 +02:00
research-messaging.md fix(team): disable teammate DM relay through lead, read user.json directly 2026-03-23 12:57:16 +02:00
research-tasks.md feat(team-management): implement initial Team Management feature with Kanban support 2026-02-17 21:10:15 +02:00
research-worktrees.md feat: use agent teams 2026-02-22 23:36:11 +02:00

Team Management Feature

Интерфейс для управления командами тиммейтов Claude Code внутри Claude Agent Teams UI (Electron).

Что делает

  • Видеть состав команды и роли участников
  • Kanban-доска с 5 колонками (TODO → IN PROGRESS → DONE → REVIEW → APPROVED)
  • Отправка сообщений тиммейтам через inbox-файлы
  • Review flow: автоматическое назначение ревьюверов или ручное ревью
  • Live updates через file watcher

Документация

Файл Содержание
research-inbox.md Формат inbox-файлов, race conditions, atomic write, доставка сообщений
research-tasks.md Формат task-файлов, .lock, .highwatermark, конкурентный доступ
research-messaging.md Сравнение подходов (inbox vs SDK vs CLI), почему выбрали inbox
kanban-design.md Kanban flow, колонки, review mechanism, kanban-state.json
implementation.md Техплан: файлы, шаги, verification
research-worktrees.md Git worktrees + teams, запуск Claude процессов из UI (Phase 2)

Ключевые решения

1. Messaging: Inbox-файлы

Единственный способ общаться с запущенными тиммейтами. SDK и CLI создают новые сессии, а не подключаются к существующим. Подробности: research-messaging.md

1.1 Roster source: members.meta.json + inboxes

  • config.json не используется как полный реестр участников (он может содержать только team-lead и служебные поля CLI).
  • Источник метаданных участников (role/color/agentType): members.meta.json.
  • Источник runtime-состава и адресации сообщений: inboxes/{member}.json.

2. Kanban Storage: Собственный файл

Kanban-позиция (REVIEW, APPROVED) хранится в kanban-state.json, а не в task metadata. Причина: metadata может быть перезаписан агентом при TaskUpdate. Подробности: kanban-design.md

3. Review Flow: Approve / Request Changes

  • Есть ревьюверы в команде → автоматическое назначение через inbox
  • Нет ревьюверов → ручное ревью юзером (Approve / Request Changes в UI)
  • При Request Changes → юзер описывает проблему (опционально) → задача к исходному owner

4. Atomic Write

Все записи через tmp + rename для предотвращения corrupted JSON.

5. Sender Identity

Отправляем from: "user". Fallback на from: "team-lead" если не работает.

Финальные решения после ревью

По итогам 3 раундов ревью (13 экспертов) приняты следующие решения:

Inbox: Atomic write + messageId verify

  • Atomic write (tmp + rename) предотвращает corrupted JSON
  • После записи читаем файл обратно и проверяем наличие нашего messageId
  • Полный CAS/retry-цикл — не нужен на MVP: проверка при следующем read достаточна
  • Риск race condition с агентом реален, но вероятность низкая

Kanban: kanban-state.json с безопасным GC

  • GC устаревших записей kanban-state выполняется ТОЛЬКО ПОСЛЕ полной загрузки tasks
  • Иначе при startup возможна race condition: GC удаляет запись до того как task-файл прочитан

Review Flow: Approve / Request Changes

  • Кнопки переименованы: Approve (вместо OK) и Request Changes (вместо Error)
  • Комментарий при Request Changes — опционален
  • reviewHistory и round-robin балансировка → Phase 2, не MVP

Members: полный список через union

  • union(config members + inbox filenames + task owners) — единственный способ получить полный список
  • owner в task-файлах — опционален (агент может не иметь owner до назначения)

Graceful Degradation

  • try/catch везде в TeamDataService — при ошибке чтения возвращаем безопасные дефолты
  • 3 состояния участника: ACTIVE / IDLE / TERMINATED
    • ACTIVE: idle < 5 минут
    • IDLE: idle > 5 минут
    • TERMINATED: получен shutdown_response с approve: true

@dnd-kit: click-to-move для MVP

  • MVP: выбор колонки через select/dropdown (click-to-move) — проще и надёжнее
  • Phase 2: полноценный D&D через @dnd-kit

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

  • FileWatcher расширение: FileWatcher.ts уже 900+ строк — добавление teams/tasks watchers нетривиально, требует отдельного спайка
  • Windows atomic rename: fs.renameSync на Windows бросает EXDEV/EBUSY при кросс-устройственном rename — нужна обёртка
  • leadSessionId интеграция: config.json содержит leadSessionId, но интеграция с session viewer (переход к сессии лида) — открытый вопрос
  • Hard Interrupt: сообщения доставляются между turns (1-30с задержка). В будущем нужен способ прервать mid-turn
  • Архивация: inbox не чистится автоматически, нужна кнопка "Архивировать"

Файловая структура Claude Code

~/.claude/
├── teams/{teamName}/
│   ├── config.json              # Конфиг команды (lead + служебные поля)
│   ├── members.meta.json        # Роли/цвета/типы участников (teammates)
│   └── inboxes/{memberName}.json  # Inbox каждого участника
└── tasks/{teamName}/
    ├── {id}.json                # Файл задачи
    ├── .lock                    # Lock-файл (0 байт)
    └── .highwatermark           # Последний ID задачи

ВАЖНО:

  • config.json не является source-of-truth для полного roster.
  • Полный roster для UI формируется как members.meta.json + inbox filenames (+ lead из config).