# task-2134: 봇 wake-up 메커니즘 안정성 개선 + standby 롤백

## ★ 프로젝트: `/home/jay/workspace/`

## 문제 (반복 발생)
dispatch.py로 팀에 작업 위임 시, 봇이 작업을 수신하지 못하는 경우 반복:
- task-2126: 7팀 봇 미수신
- task-2129: 6팀 봇 "작업 지시를 기다리고 있습니다" 2분 대기
- task-2130: 5팀 봇 미수신 (보고서 없음 = 작업 실행 안 됨)
- task-2132: 1팀 봇이 이전 세션(task-2056)에 연결

추가 문제: dispatch 시 member-status를 standby로 설정하는데, 봇이 작업 수신 실패 시 **standby가 영원히 남음** (1팀 아테나/아르고스 사례)

## 현재 메커니즘 (dispatch.py L1306~1355)

```
1. 봇 프로세스 없으면 → cokacdir로 세션 시작 메시지 전송
2. 15초 대기 (5초 × 3회 폴링)
3. 실패 시 → 딜레이 15초 후 cron 전송 (absolute 시간)
```

### 근본 원인: cron absolute 시간과 봇 세션 시작의 race condition
- cron이 absolute 시간으로 전송되는데, 봇 세션이 아직 안 열림
- 세션이 열린 후에는 이미 cron 시간이 지나서 수신 못 함

## 수정 사항 (2가지)

### 수정 1: wake-up 후 프로세스 확인 대기 시간 확장 + cron 딜레이 증가

```python
# 현재: 15초 대기 후 15초 딜레이
# 수정: 45초 대기 후 30초 딜레이 (총 75초)

# _wake_up_bot() 함수:
# - Stage 2 대기: 15초 → 45초 (5초 × 9회)
# - 프로세스 확인 성공 시: cron 딜레이 30초
# - 프로세스 미확인 시: cron 딜레이 60초 + 재시도 1회

# lazy-start 딜레이도 15초 → 45초로 증가
```

### 수정 2: dispatch 실패 시 member-status 롤백

```python
# dispatch 완료 후 member-status를 standby로 설정하는 _update_member_status_on_dispatch() 에:
# - cron 전송 성공 확인 후에만 standby 설정
# - 또는: 타임아웃 롤백 — 5분 후에도 task-timer running이 없으면 자동 idle 복원
# - 방법: dispatch 시 "rollback_at" 시각을 기록, 별도 체커가 확인

# 더 간단한 방법:
# dispatch.py 끝에서 "5분 후 체크" cron을 추가 등록:
# → 5분 후: task-timers.json에 해당 task_id running이 없으면 member-status 전원 idle 복원
```

### 수정 2 구현 (간단한 방식):
`_update_member_status_on_dispatch()` 호출 후, 별도 cron으로 "상태 체크" 예약:

```python
# dispatch 성공 후:
rollback_prompt = f"python3 -c \"
import json
from datetime import datetime, timezone
# task-timers에 {task_id} running 있는지 확인
with open('/home/jay/workspace/memory/task-timers.json') as f:
    d = json.load(f)
tasks = d.get('tasks', {})
task = tasks.get('{task_id}', {})
if task.get('status') != 'running':
    # running 아님 = 봇이 작업 수신 못 함 → member-status 롤백
    sf = '/home/jay/workspace/memory/events/member-status.json'
    with open(sf) as f: ms = json.load(f)
    now = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
    for name in {team_member_ids}:
        if name in ms.get('members', {}):
            ms['members'][name] = {'status': 'idle', 'since': now, 'task': None}
    ms['updated_at'] = now
    with open(sf, 'w') as f: json.dump(ms, f, indent=2, ensure_ascii=False)
    print('[rollback] member-status idle 복원 완료')
else:
    print('[rollback] task running 확인, 롤백 불필요')
\""

# 5분 후 실행되는 cron 등록
cokacdir --cron rollback_prompt --at "5m" --chat ... --key ...
```

## ★ 먼저 읽을 파일
- `/home/jay/workspace/dispatch.py` — L1306~1355 (_wake_up_bot)
- `/home/jay/workspace/dispatch.py` — _update_member_status_on_dispatch 함수 (task-2126에서 추가)
- `/home/jay/workspace/dispatch.py` — lazy-start 관련 코드 (grep "lazy" dispatch.py)

## 검증 시나리오 (이게 되면 성공)

### 시나리오 1: 슬립 봇에 dispatch → 정상 수신
1. 모든 봇 프로세스 없는 상태
2. dev3-team에 테스트 작업 dispatch
3. 봇 세션 시작 → 작업 수신 → member-status 정상 반영
4. 수동 재전송 불필요

### 시나리오 2: wake-up 실패 시 자동 롤백
1. 존재하지 않는 봇에 dispatch (의도적 실패)
2. 5분 후 member-status가 자동으로 idle 복원
3. 대시보드에 standby가 영원히 남지 않음

### 시나리오 3: 기존 정상 봇 회귀 없음
1. 이미 돌고 있는 봇에 dispatch → 기존대로 동작

## 완료 시그니처
- wake-up 대기 시간 45초로 확장
- cron 딜레이 30~60초로 증가
- dispatch 실패 시 5분 후 자동 rollback
- 기존 봇 회귀 없음

## 레벨
- critical

## 프로젝트
- dev-system
