# Итерация 05 — Testing + Polish (production-ready)

Эта итерация закрывает **качество**: тесты на критические пути (read/write), фиксация edge cases, UX-polish (empty/error/loading), и небольшие оптимизации под реальные объёмы inbox/tasks.

Основание:
- `docs/team-management/implementation.md` (**Iteration 5: Testing + Polish**)
- `docs/team-management/research-inbox.md` (race + verify, messageId)
- `docs/team-management/research-tasks.md` (task write verify)
- `docs/team-management/kanban-design.md` (GC order, mapping)

---

## Цель итерации

- Добавить **тесты** на:
  - kanban-state чтение/запись/GC
  - inbox read/write (atomic + verify + retry + lock)
  - task status write verify (request changes)
  - IPC guards и handlers (валидаторы + happy/err paths)
  - store coalesce/throttle на `team:change`
- Улучшить UX:
  - ясные empty/error/loading состояния для всех team-panels
  - аккуратные сообщения об ошибках write-path (inbox/task)
  - ограничение и оптимизация рендера больших списков
- Подготовить основу для Phase 2 (D&D, archive, round-robin), не реализуя их.

---

## Не-цели

- E2E/UI automation (можно позже отдельным треком).
- Полный performance-профайлинг приложения.
- Редизайн UI — только точечный polish.

---

## Definition of Done (DoD)

- **Тесты**
  - Добавлены новые тесты (см. ниже), все проходят локально.
  - `pnpm test` зелёный.
  - `pnpm typecheck` зелёный.
- **UX**
  - Нет “пустых серых экранов”: каждый экран имеет понятное состояние.
  - Ошибки write-path показываются пользователю понятным текстом.
- **Надёжность**
  - Все write-path используют atomic write.
  - Верификация после записи включена для inbox и task status.

---

## Тестовая стратегия (конкретно что проверяем)

### 1) TeamKanbanManager

- `getState()`:
  - ENOENT → default state
  - corrupted JSON → default + warning (если warnings протаскиваются)
- `updateTask()`:
  - set column → появляется запись с `movedAt`
  - remove → запись исчезает
- `garbageCollect()`:
  - удаляет только невалидные taskId
  - dirty-check: не пишет файл, если удалять нечего
- **GC order**:
  - тест на `TeamDataService.getTeamData()` что GC вызывается **после** чтения tasks (контракт из `kanban-design.md`)

### 2) Inbox write-path

- `sendMessage()`:
  - пишет `messageId`, `timestamp`, `read:false`
  - после записи verify находит `messageId`
- Race simulation (упрощённо):
  - смоделировать “потерю” (подменой read-back) → retry с backoff вызывается нужное число раз и в итоге error/ok как ожидается
- `withInboxLock()`:
  - два параллельных send в один inbox → оба сообщения сохраняются

### 3) Task status write-path

- `updateStatus()`:
  - меняет только `status`
  - verify после write подтверждает изменение
  - конфликт (подменить файл после write) → ошибка, UI сможет показать warning

### 4) IPC / Guards

- `validateTeamName`, `validateTaskId`, `validateMemberName`:
  - reject path traversal (`../`, слеши, пробелы, пустые)
  - accept валидные имена
- Handlers:
  - invalid args → `IpcResult.success=false`
  - happy path → `success=true`

### 5) Renderer store

- Coalesce/throttle на `team:change`:
  - серия событий <300ms → один refresh
  - если team не виден → не делает лишние `getData` (но обновляет list если это заложено)

---

## Рекомендуемая структура тестов (адаптировать под текущее дерево)

```
test/
├── main/
│   ├── services/team/
│   │   ├── TeamKanbanManager.test.ts
│   │   ├── TeamInboxReader.test.ts        # read (list + merge + sort)
│   │   ├── TeamInboxWriter.test.ts        # sendMessage (atomic + verify + retry + lock)
│   │   ├── TeamTaskWriter.test.ts
│   │   └── TeamDataService.test.ts        # orchestration + GC order
│   └── ipc/
│       ├── guards.test.ts                 # расширить (team/task/member/from)
│       └── teams.test.ts                  # новые каналы/handlers
├── renderer/
│   └── store/
│       └── teamSlice.test.ts              # refresh, send, review actions, throttle
└── fixtures/team/
    ├── teams/
    │   └── my-team/
    │       ├── config.json
    │       ├── kanban-state.json
    │       └── inboxes/
    │           ├── alice.json
    │           └── reviewer.json
    └── tasks/
        └── my-team/
            ├── 12.json
            ├── 13.json
            ├── .lock
            └── .highwatermark
```

Важно:
- `.lock`/`.highwatermark` должны присутствовать в fixture, чтобы гарантировать “пропуск мусорных файлов”.
- Не используем реальный `~/.claude` в тестах.

---

## UX/Polish checklist

- **Empty states**
  - Нет tasks → “Нет задач в этой команде”
  - Нет сообщений → “Нет сообщений” + подсказка “Отправь сообщение”
  - Нет reviewers → в REVIEW показывать “Manual review” (без авто-assign)
- **Error states**
  - Inbox write verify failed → “Сообщение записано, но не подтверждено (race). Попробуй отправить ещё раз.”
  - Task status verify failed → “Не удалось обновить статус задачи (возможен конфликт с агентом).”
- **Loading**
  - Skeleton для TeamDetailView (3 панели)
- **Performance**
  - ActivityTimeline: рендерим только последние N (например 200), кнопка “Показать ещё” (не обязателен infinite scroll)
  - Если tasks > 200: предусмотреть простую фильтрацию по owner/status (минимально)
- **Accessibility**
  - Кнопки имеют понятные `aria-label`
  - Навигация по клавиатуре: focus ring виден

---

## Порядок работ (runbook)

### CP0 — стабилизируем контракты

- Пройтись по типам `TeamData`, `InboxMessage`, kanban types.
- `pnpm typecheck`

### CP1 — тесты main/services

- Добавить fixtures.
- Написать тесты для kanban/inbox/task writer/service orchestration.
- `pnpm test` (обязательно запускать сразу после добавления/правки тестов)

### CP2 — тесты IPC/guards

- Расширить `guards.test.ts`
- Добавить `teams.test.ts` для новых handler’ов
- `pnpm test`

### CP3 — тесты store + polish

- teamSlice tests на coalesce и actions.
- UI polish по чеклисту.
- `pnpm typecheck` + `pnpm test`

---

## Риски и митигации

- **Тесты станут “флейковыми”** из-за таймеров/throttle:
  - использовать fake timers и явный flush.
- **Слишком много моков Electron**:
  - держать единый helper mock `electronAPI` в `test/mocks/`.
- **Большие списки сообщений**:
  - ограничение N + простой “show more” снимают риск O(n) перерендера.

---

## Минимальный чеклист регрессии (ручной)

1) Teams → открыть команду → kanban/задачи/участники видны  
2) Move DONE → REVIEW → состояние сохранилось (после перезапуска app остаётся)  
3) Отправить сообщение → delivered + появилось в Activity  
4) Request Review → карточка в REVIEW + (если reviewer задан) сообщение ушло  
5) Request Changes → task.status стал `in_progress` + owner получил сообщение  
6) Любое изменение файлов `~/.claude/teams/**` / `~/.claude/tasks/**` → UI обновился в пределах ~1с  

