# Task: 팀 단톡 봇 연동 + 조직도 자동 연동 + 프로필 포맷 개선

## 작업 레벨: Lv.2

## 변경 대상
- `/home/jay/workspace/group_chat.py` (기존 파일 수정)
- `/home/jay/workspace/config/personas.json` → 삭제 또는 이모지 매핑 전용으로 축소
- `/home/jay/workspace/tests/test_group_chat.py` (테스트 업데이트)

## 변경 사항 3가지

### 1. 봇 토큰 변경
**Before**: bot_settings.json의 `c119085addb0f8b7.token` (Bot A / 아누)
**After**: 환경변수 `GROUP_CHAT_BOT_TOKEN` 사용

```python
# .env.keys에 추가됨: export GROUP_CHAT_BOT_TOKEN="..."
# 로드 방법:
token = os.environ.get("GROUP_CHAT_BOT_TOKEN")
if not token:
    # 폴백: .env.keys 파일에서 직접 파싱
    env_path = "/home/jay/workspace/.env.keys"
    # ... 파싱 로직
```

- bot_settings.json 읽기 로직 제거
- GROUP_CHAT_BOT_TOKEN 환경변수에서 로드
- 폴백: `/home/jay/workspace/.env.keys` 파일에서 파싱

### 2. 조직도 자동 연동
**Before**: `config/personas.json`에서 페르소나 하드코딩 로드
**After**: `/home/jay/workspace/memory/organization-structure.json`에서 동적 로드

조직도 JSON 구조:
```
structure.columns.teams[] →
  team_id: "development-office" → sub_teams[] →
    각 sub_team: {sub_team_id, sub_team_name, lead: {id, name, role}, members: [{id, name, role}]}
  team_id: "red-team" → lead: {id, name, role}
structure.rows.centers[] →
  각 center: {center_name, lead: {id, name, role}}
```

파싱 로직:
```python
def load_personas_from_org() -> dict:
    """organization-structure.json에서 페르소나 동적 로드"""
    org_path = "/home/jay/workspace/memory/organization-structure.json"
    with open(org_path) as f:
        org = json.load(f)

    personas = {}

    # 1. 개발실 하위 팀들 (sub_teams)
    for team in org["structure"]["columns"]["teams"]:
        if team.get("team_id") == "development-office":
            for sub_team in team.get("sub_teams", []):
                team_name = sub_team["sub_team_name"]  # "개발1팀"
                # 팀장
                lead = sub_team.get("lead", {})
                if lead and lead.get("status") == "active":
                    personas[lead["id"]] = {
                        "name": lead["name"].split(" (")[0],  # "헤르메스"
                        "team": team_name,
                        "role": lead["role"],  # "개발1팀장"
                        "expertise": lead.get("expertise", {}).get("primary", ""),
                        "personality": lead.get("expertise", {}).get("style", ""),
                        "persona_desc": lead.get("persona", "")
                    }
                # 멤버
                for member in sub_team.get("members", []):
                    if member.get("status") in ("active", "available"):
                        personas[member["id"]] = {
                            "name": member["name"].split(" (")[0],
                            "team": team_name,
                            "role": member["role"],
                            "expertise": member.get("expertise", {}).get("primary", ""),
                            "personality": member.get("expertise", {}).get("style", ""),
                            "persona_desc": member.get("persona", "")
                        }

        # 2. 레드팀
        elif team.get("team_id") == "red-team":
            lead = team.get("lead", {})
            if lead and lead.get("status") == "active":
                personas[lead["id"]] = {
                    "name": lead["name"].split(" (")[0],
                    "team": "레드팀",
                    "role": lead["role"],
                    "expertise": lead.get("expertise", {}).get("primary", ""),
                    "personality": lead.get("expertise", {}).get("style", ""),
                    "persona_desc": lead.get("persona", "")
                }

    # 3. 횡단조직 (QC, DevOps, 디자인)
    for center in org["structure"]["rows"]["centers"]:
        lead = center.get("lead", {})
        if lead and lead.get("status") == "active":
            personas[lead["id"]] = {
                "name": lead["name"].split(" (")[0],
                "team": center["center_name"],
                "role": lead["role"],
                "expertise": lead.get("expertise", {}).get("primary", ""),
                "personality": lead.get("expertise", {}).get("style", ""),
                "persona_desc": lead.get("persona", "")
            }

    return personas
```

**아누(anu)는 제외** — 아누는 오케스트레이터이므로 페르소나 대화에 참여하지 않음. 아누의 메시지는 별도 포맷으로 전송 (시스템 메시지).

### 3. 프로필 포맷 변경
**Before**: `<b>⚡ [헤르메스]</b> 메시지`
**After**: `<b>⚡ 헤르메스(개발1팀/팀장)</b> 메시지`

포맷 함수:
```python
def format_persona_tag(persona_key: str, personas_data: dict) -> str:
    p = personas_data[persona_key]
    emoji = EMOJI_MAP.get(persona_key, "💬")
    # "헤르메스(개발1팀/팀장)" 형태
    return f"{emoji} {p['name']}({p['team']}/{p['role']})"
```

이모지 매핑은 코드 내 상수로 유지 (조직도에 이모지 필드 없음):
```python
EMOJI_MAP = {
    "hermes": "⚡", "odin": "👁️", "ra": "☀️",
    "vulcan": "🔥", "iris": "🌈", "athena": "🏛️", "argos": "🔍",
    "thor": "🔨", "freya": "✨", "mimir": "📚", "heimdall": "🛡️",
    "anubis": "⚱️", "isis": "🌙", "thoth": "📜", "horus": "🦅",
    "loki": "🎭", "venus": "🎨", "janus": "🚪", "maat": "⚖️",
}
```

## 시스템 프롬프트 업데이트
페르소나별 시스템 프롬프트에 조직도 정보 반영:
```
당신은 {name}입니다. {team}의 {role}입니다.
{persona_desc}
전문 분야: {expertise}
성격: {personality}

규칙:
- 2-4문장 이내로 짧게 응답
- 한국어 사용
- 유저(제이회장님)를 "제이회장님"이라 호칭
- 다른 팀원은 이름으로 직접 호칭
- 자연스러운 대화체
```

## 검증 항목
1. GROUP_CHAT_BOT_TOKEN 환경변수로 봇 토큰 로드 확인
2. organization-structure.json에서 페르소나 로드 확인 (20명 - 아누 제외 = 19명)
3. 조직도에 새 멤버 추가 후 group_chat.py 재시작 → 자동 반영 확인
4. 프로필 포맷: "헤르메스(개발1팀/팀장)" 형태 확인
5. 기존 기능 유지: 입장/퇴장 시퀀스, 타임아웃, MAX_AUTO_TURNS 등
6. 기존 테스트 + 새 테스트 전체 PASS

## 주의사항
- organization-structure.json은 읽기 전용. 수정하지 말 것
- 아누(id: "anu")는 페르소나 목록에서 제외
- status가 "planned"인 팀/센터는 제외 (active/available만)
- .env.keys 파일 절대 수정 금지 (이미 토큰 추가됨)
- config/personas.json은 삭제하지 말고 폴백용으로 유지 (조직도 로드 실패 시)
