# 신호등 체계 스펙 (Traffic Light System Spec)

> 작성일: 2026-04-15
> 최종 수정: 2026-04-15 (봇 차용 로직 병합)
> 근거: 제이회장님 직접 정의 (2026-04-15) + 런타임 검증 완료
> 반복 오류 방지용 — 이 문서가 신호등 구현의 단일 소스(Single Source of Truth)

---

## 1. 상태 정의 (3가지만 존재)

| 상태 | 색상 | 의미 |
|------|------|------|
| **유휴** | 회색 | 아무 작업도 없음. 팀에 할당된 task가 없는 상태 |
| **대기** | 노란색 | 팀에 task가 할당되었지만, 아직 이 멤버가 실제 호출되지 않음 |
| **작업중** | 초록색 | 팀장이 이 멤버를 호출하여 실제 작업 수행 중 |

---

## 2. 상태 전이 규칙

### 2.1 dev팀 자체 작업 시
```
dispatch.py로 dev팀에 직접 작업 위임
  → 팀장: 작업중 (초록)
  → 팀원 전원: 대기 (노란) ← 유휴가 아님!
```

### 2.2 팀장이 subagent(팀원) 호출 시
```
팀장이 특정 팀원에게 작업 위임
  → 해당 팀원: 대기(노란) → 작업중(초록)
  → 나머지 팀원: 대기(노란) 유지
```

### 2.3 팀원 작업 완료 시
```
팀원의 개별 작업 완료
  → 해당 팀원: 작업중(초록) → 대기(노란)
  → 팀 전체 작업은 아직 진행 중
```

### 2.4 팀 전체 작업 완료 시 (.done 파일 생성)
```
팀장이 .done 파일 생성
  → 팀장: 작업중(초록) → 유휴(회색)
  → 팀원 전원: 대기/작업중 → 유휴(회색)
  → 팀 전체: 유휴
```

---

## 3. 논리적/복합팀 봇 차용 (Borrowed Tasks)

### 3.1 개념
marketing, content, design, consulting, publishing, composite 등 **논리적 팀**은 자체 봇이 없음.
dispatch 시 dev팀 봇을 **차용(borrow)**하여 사용.

### 3.2 차용 시 상태 전이
```
marketing 팀에 작업 위임 → bot-b (dev1팀 봇) 배정
  → dev1팀 카드:
    - has_running_tasks = True
    - logical_team_using = "마케팅팀"
    - borrowed_tasks = [{task_id, team_id: "marketing", ...}]
  → dev1팀 팀장(헤르메스): 작업중 (초록)
  → dev1팀 팀원: 대기 (노란)
  → marketing 카드: "1팀봇 사용" 배지 표시
```

### 3.3 차용 task 시각 구분
- dev팀 자체 task: 초록 도트 (`bg-emerald-400`)
- 차용 task: **보라색 도트** (`bg-violet-400`)

### 3.4 구현 위치
- **백엔드**: `data_loader.py` → `_enrich_bot_activity()` 함수
  - task의 `team_id`가 봇의 dev팀과 다르면 → `borrowed_tasks` 리스트에 추가
  - `logical_team_using` 필드에 차용 팀 이름 설정
  - 복수 논리팀 동시 차용 시 `"+"` 결합 (예: "마케팅팀+컨텐츠팀")
- **프론트엔드**: `App.js` → `ownTasks + borrowedTasks` 병합하여 `allTasks` 전달
- **프론트엔드**: `utils.js` → `isBorrowed` 조건으로 보라색 도트 렌더링

### 3.5 필수 조건
borrowed_tasks가 동작하려면 task-timers.json에 **`bot` 필드가 반드시 존재**해야 함.
- dispatch.py로 위임 시: 자동 배정됨 ✅
- task-timer.py로 수동 start 시: bot 필드 없음 → borrowed_tasks 미동작 ⚠️

### 3.6 검증 완료 (2026-04-15 런타임 테스트)
```
marketing 팀에 task-9999 생성 + bot-b 배정
  → /api/bot-activity 응답:
    dev1: has_running=True, logical_team_using=마케팅팀,
          borrowed_tasks=[{task_id: task-9999, team_id: marketing, ...}]
  → 정상 동작 확인 ✅
```

---

## 4. 상태 전이 다이어그램

```
                    dispatch 위임
                        │
    ┌───────────────────┼───────────────────┐
    ▼                   ▼                   ▼
 [팀장]             [팀원A]             [팀원B]
 작업중(초록)       대기(노란)          대기(노란)
    │                   │
    │ 팀장이 A 호출     │
    │──────────────────►│
    │                   ▼
    │              작업중(초록)
    │                   │
    │    A 작업 완료    │
    │◄──────────────────│
    │                   ▼
    │              대기(노란)
    │
    │ .done 생성
    ▼
 유휴(회색)         유휴(회색)          유휴(회색)
```

### 논리적 팀 차용 시 다이어그램

```
marketing 작업 위임 → bot-b 배정
    │
    ▼
 [dev1 팀장]        [dev1 팀원]        [marketing 카드]
 작업중(초록)       대기(노란)         "1팀봇 사용" 배지
    │
    │  task 표시: 보라색 도트 (차용)
    │
    │ .done 생성
    ▼
 유휴(회색)         유휴(회색)          배지 제거
```

---

## 5. 핵심 원칙

1. **팀 작업 시작 = 팀원 전원 대기(노란)**. 유휴(회색)로 남아있으면 안 됨
2. **실제 호출 = 작업중(초록)**. 팀장이 subagent를 실제로 호출한 팀원만 초록
3. **개별 완료 = 대기 복귀(노란)**. 팀 작업이 끝나지 않았으므로 유휴가 아님
4. **팀 완료 = 전원 유휴(회색)**. .done 파일 기준
5. **차용 task = 보라색 도트**. dev팀 자체 task(초록)와 시각 구분 필수
6. **borrowed_tasks 동작 = bot 필드 필수**. task-timers.json에 bot 배정 없으면 차용 미감지

---

## 6. 구현 매핑 (코드 위치)

### 6.1 백엔드
| 기능 | 파일 | 함수/위치 |
|------|------|-----------|
| 멤버 상태 결정 | data_loader.py | `get_member_status()` — is_lead로 working/standby 분기 |
| 봇 활동 enrichment | data_loader.py | `_enrich_bot_activity()` — borrowed_tasks, logical_team_using |
| 멤버 상태 enrichment | data_loader.py | `_enrich_member_status()` — member-status.json 보강 |

### 6.2 프론트엔드
| 기능 | 파일 | 컴포넌트/위치 |
|------|------|-------------|
| 상태 색상 렌더링 | utils.js | `StatusDot` — working→초록, standby→노란, idle→회색 |
| 멤버 행 상태 결정 | utils.js | `MemberRow` — hasRunningTasks + isLead로 분기 |
| 인원 현황 바 | App.js | borrowedTasks.length > 0 반영 |
| 팀 카드 task 병합 | App.js | ownTasks + borrowedTasks → allTasks |
| 차용 도트 색상 | utils.js | isBorrowed → `bg-violet-400` |

### 6.3 API 엔드포인트
| API | 용도 |
|-----|------|
| `/api/member-status` | 멤버별 상태 (working/standby/idle) |
| `/api/bot-activity` | 봇별 활동 (borrowed_tasks, logical_team_using) |
| `/api/teams` | 팀 카드 데이터 |

---

## 7. 과거 오류 패턴 (반복 발생 방지)

### 7.1 팀원이 유휴로 표시 (task-1854에서 수정)
- **원인**: `MemberRow`에서 `hasRunningTasks && isLead`만 체크 → 팀원 누락
- **수정**: `hasRunningTasks && !isLead` → `"standby"` 분기 추가

### 7.2 전원 작업중으로 표시
- **원인**: `get_member_status()`가 `is_lead` 무시하고 전원 `"working"` 반환
- **수정**: `is_lead`이면 `"working"`, 아니면 `"standby"` 반환

### 7.3 서버 미재시작으로 코드 미반영
- **원인**: data_loader.py 수정 후 서버 재시작 안 함
- **수정**: 코드 수정 후 반드시 서버 재시작 또는 PID kill + 재시작

### 7.4 borrowed_tasks 미동작
- **원인**: task-timers.json에 `bot` 필드 누락 (수동 task-timer start 시)
- **수정**: dispatch.py 통해 위임하면 bot 자동 배정됨. 수동 start 시 주의.
