# task-1405.1 완료 보고서

**S**: dispatch.py는 dev팀(고정 봇 할당)과 논리적팀(design/marketing/content 등, 동적 봇 선택)의 봇 라우팅을 관리하며, 봇 충돌 검사(`_get_busy_bots_info`)로 동일 봇의 다중 작업을 방지한다.

**C**: task-1400.1(design)이 bot-e를 동적 점유 중인데 task-1403.1(dev4-team)도 bot-e에 위임되는 충돌이 발생했다. `_find_available_bot()`의 봇 선택과 `_patch_timer_metadata(bot=...)`의 기록이 분리되어 있어, 기록 전에 다른 dispatch가 실행되면 충돌을 감지하지 못하는 경합 조건이 존재했다.

**Q**: 논리적팀과 dev팀 간 봇 충돌을 원천 차단할 수 있는가?

**A**: `_select_and_reserve_bot()` 함수를 신설하여 파일 락 내에서 봇 선택과 타이머 기록을 원자적으로 수행하도록 수정. dev팀도 봇 할당 즉시 `bot` 필드를 조기 기록하여 논리적팀 dispatch의 busy bot 수집에 반영되도록 했다. pytest 158건 전체 통과 (기존 149 + 신규 9).

## 산출물

- `/home/jay/workspace/dispatch.py` — `_select_and_reserve_bot()` 함수 추가, composite/DYNAMIC_BOT_TEAMS/dev팀 경로 수정
- `/home/jay/workspace/tests/test_dispatch.py` — `TestLogicalTeamBotConflict`(5개), `TestSelectAndReserveBot`(4개) 테스트 추가
- `/home/jay/workspace/memory/specs/bot-collision-prevention.md` — 봇 충돌 방지 규칙 문서
- `/home/jay/workspace/memory/specs/anu-guide.md` — 6.2절 업데이트, 6.3절 신설

## 변경 상세

### 1. `_select_and_reserve_bot()` 신설 (dispatch.py line ~293)
- `fcntl.LOCK_EX` 파일 락 내에서 busy bot 수집 → 봇 선택 → task-timers.json 즉시 기록
- 기존 `_find_available_bot()`은 하위 호환용 유지

### 2. composite 경로 수정 (dispatch.py line ~954)
- `_find_available_bot()` → `_select_and_reserve_bot(task_id, ...)` 교체

### 3. DYNAMIC_BOT_TEAMS 경로 수정 (dispatch.py line ~1280)
- `_find_available_bot()` → `_select_and_reserve_bot(timer_task_id, ...)` 교체

### 4. dev팀 early bot patch (dispatch.py line ~1305-1307)
- `bot_id_meta` 설정 직후 `_patch_timer_metadata(timer_task_id, bot=bot_id_meta)` 호출 추가

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **경합 조건: 봇 선택-기록 분리** — `_select_and_reserve_bot()`으로 원자화
2. **dev팀 bot 필드 미기록** — 충돌 검사 전 `_patch_timer_metadata(bot=...)` 조기 호출 추가
3. **아누 가이드 content 팀 누락** — 6.2절에 content 추가, 6.3절 신설

### 범위 외 미해결 (0건)

## 테스트 결과

```
tests/test_dispatch.py: 158 passed in 0.86s
```

- 기존 149개 전체 통과 (회귀 없음)
- 신규 9개 전체 통과:
  - `TestLogicalTeamBotConflict`: 5개 (design/content 봇 충돌 차단, completed 허용, bot 필드 없음, 멀티팀)
  - `TestSelectAndReserveBot`: 4개 (봇 선택, busy 스킵, timer 기록, all busy RuntimeError)

## 모델 사용 기록

- 아누비스 (백엔드) / dispatch.py 수정 / sonnet
- 토트 (테스터) / 테스트 작성 / sonnet
