# 와치독 재위임 프로세스 개선 — 원인 분석 + /stop 후 재위임

## Lv.2 작업

## 문제 2가지

### 1. 원인 분석 없이 재위임
와치독이 STALLED 판정 → 즉시 재위임. 왜 죽었는지 원인을 분석/기록하지 않음.

### 2. 봇에 /stop 안 보내고 재위임
`kill PID`로 프로세스만 죽이고, cokacdir 봇 자체는 /stop 하지 않음.
→ 봇이 좀비 상태로 남아있고, 새 작업 dispatch 시 이전 세션 잔존으로 혼동.

## 수정
`/home/jay/workspace/scripts/session-watchdog.sh`

### 재위임 단계 변경 (현재 → 개선)

현재:
```
STALLED 판정 → kill PID → cokacdir 스케줄 제거 → task-timer end → dispatch.py 재위임
```

개선:
```
STALLED 판정
  → 1. 원인 분석 (왜 죽었는지 기록)
  → 2. cokacdir /stop 명령 (봇 세션 완전 종료)
  → 3. 봇 idle 확인 (2~3초 대기)
  → 4. kill PID (잔존 프로세스 정리)
  → 5. cokacdir 스케줄 제거
  → 6. task-timer end
  → 7. dispatch.py 재위임
```

### 1. 원인 분석 추가
STALLED 판정 직후, 로그에 원인 기록:

```bash
# 원인 분석
DEATH_REASON="unknown"
if [[ ! -d "/proc/$PID" ]]; then
    # PID 자체가 없음 → 비정상 종료 또는 context/usage limit
    DEATH_REASON="process_gone"
elif [[ "$ELAPSED" -gt "$STALE_THRESHOLD" ]]; then
    DEATH_REASON="heartbeat_stale_${ELAPSED}s"
fi

# 봇 로그에서 추가 원인 추적
BOT_LOG=$(find /home/jay/.cokacdir/logs -name "*${SCHEDULE_ID}*" -newer "$HEARTBEAT_FILE" 2>/dev/null | head -1)
if [[ -n "$BOT_LOG" ]]; then
    if grep -q "context_limit\|token_limit" "$BOT_LOG" 2>/dev/null; then
        DEATH_REASON="context_limit"
    elif grep -q "usage_limit\|rate_limit" "$BOT_LOG" 2>/dev/null; then
        DEATH_REASON="usage_limit"
    elif grep -q "error\|crash\|panic" "$BOT_LOG" 2>/dev/null; then
        DEATH_REASON="error_crash"
    fi
fi

log "${TASK_ID}: 사망 원인 = ${DEATH_REASON}"
```

원인을 `memory/logs/watchdog-deaths.jsonl`에 JSONL로 기록:
```json
{"task_id":"task-1772.1","team":"dev2-team","reason":"context_limit","timestamp":"2026-04-13T10:39:16","heartbeat_age_s":650}
```

### 2. cokacdir /stop 추가
재위임 전에 봇에 /stop 명령:

```bash
# 봇 키 가져오기
COKACDIR_KEY=$(get_cokacdir_key "$TEAM_ID")
BOT_CHAT_ID=$(get_bot_chat_id "$TEAM_ID")

if [[ -n "$COKACDIR_KEY" && -n "$BOT_CHAT_ID" ]]; then
    log "${TASK_ID}: /stop 명령 전송 (bot=${BOT_CHAT_ID})"
    /usr/local/bin/cokacdir --sendmsg "/stop" --chat "$BOT_CHAT_ID" --key "$COKACDIR_KEY" >> "$LOG_FILE" 2>&1 || true
    sleep 3  # 봇이 /stop 처리할 시간
fi
```

### 3. .done 파일 체크 추가 (bonus)
STALLED 판정 전에 .done 파일 존재 여부 확인 — 이미 완료된 작업은 재위임하지 않음:

```bash
DONE_FILE="${WORKSPACE}/memory/events/${TASK_ID}.done"
if [[ -f "$DONE_FILE" ]]; then
    log "${TASK_ID}: .done 파일 존재 → 이미 완료, 재위임 스킵"
    continue
fi
```

## 참조
- 와치독 스크립트: `/home/jay/workspace/scripts/session-watchdog.sh` (234줄)
- cokacdir CLI: `/usr/local/bin/cokacdir`
- 봇 설정: `/home/jay/workspace/memory/bot_settings_sync.json` (봇별 chat_id, key)
- heartbeat 디렉토리: `/home/jay/workspace/heartbeats/`

## 검증 시나리오
1. 정상 완료된 작업(.done 존재) → 와치독이 재위임하지 않음 확인
2. STALLED 판정 → `watchdog-deaths.jsonl`에 원인 기록 확인
3. 재위임 전 /stop 명령 전송 로그 확인
4. /stop 후 3초 대기 후 dispatch.py 호출 순서 확인
5. 와치독 전체 사이클 실행 시간 30초 이내 유지 확인

## 보고서
`/home/jay/workspace/memory/reports/task-{TASK_ID}.md`
