# task-616.1: .done 프로토콜 근본 재설계 (Pull 모델 전환)

## 배경
.done 프로토콜이 3번 수정(607.1, 609.1, 613.1) 후에도 실패. 에이전트 미팅(2026-03-16) 전원 합의로 Push→Pull 전환 결정.
- 미팅 기록: `memory/meetings/2026-03-16-done-protocol-redesign.md`
- 근본 원인: cokacdir --cron으로 새 아누 세션을 깨우지만, 새 세션은 현재 대화와 단절되어 보고가 제이회장님에게 안 보임
- 해결 방향: 아누가 매 대화 시작 시 whisper를 통해 직접 .done 파일을 감지 (Pull 모델)

## 상태 전이 (새 설계, 2단계)
```
팀 완료 → .done 파일 생성 (기존과 동일)
  ├─ 체인 중간 Phase: notify-completion.py → chain_manager.py → dispatch.py 직접 호출 (기존 유지, 변경 없음)
  └─ 체인 마지막 / 독립 작업: 텔레그램 텍스트 알림만 전송 (아누 세션 깨우기 X)

아누 세션 시작 → whisper-compile.py가 *.done 스캔 → "task-X 완료" 브리핑
아누가 보고서 읽고 보고 → .done → .done.acked rename

.done (미처리) / .done.acked (처리 완료) — 2단계만 존재
```

## 수정 사항

### 1. notify-completion.py 수정
현재 경로: `/home/jay/workspace/scripts/notify-completion.py`

#### 체인 중간 Phase (변경 없음)
- `check_chain_status()`로 체인 확인 → `in_chain=True, is_last=False` → dispatch.py 직접 호출
- 이 경로는 현재 정상 작동 중. 건드리지 말 것.

#### 체인 마지막 / 독립 작업 (변경 필요)
- `wake_anu_session()` 호출 **제거**
- 대신 `send_telegram_notification()`으로 텔레그램 텍스트만 전송
  - 메시지 형식: `✅ {task_id} 완료. 보고서: memory/reports/{task_id}.md`
  - 아누 세션 깨우기(cokacdir --cron) 절대 금지
- `.done` 파일을 건드리지 않음 (rename 금지, 삭제 금지, .done.notified 생성 금지)

#### 제거 대상
- `create_done_notified()` 함수 전체 제거
- `wake_anu_session()` 호출부 제거 (함수 자체는 남겨도 됨, 호출만 제거)
- `.done.notified` 관련 로직 전체 제거
- `--retry` 플래그 관련 로직 제거
- `build_prompt()` 함수의 completion-handler 관련 내용 제거

### 2. done-watcher.sh 수정
현재 경로: `/home/jay/workspace/scripts/done-watcher.sh`

#### 전면 재작성
```bash
#!/bin/bash
# done-watcher.sh - stale .done 감지 + 에스컬레이션 전용
# 정리(archive) 역할 완전 제거. 아누만 .done → .done.acked 가능.

EVENTS_DIR="/home/jay/workspace/memory/events"
LOG="/home/jay/workspace/logs/done-protocol.log"

log() {
    echo "[$(date -Iseconds)] [done-watcher] $1" >> "$LOG"
}

# Case 1: stale .done 감지 (30분 이상 미처리 → 텔레그램 경보)
for done_file in $(find "$EVENTS_DIR" -maxdepth 1 -name "*.done" ! -name "*.done.*" -type f 2>/dev/null); do
    task_id=$(basename "$done_file" .done)
    file_age=$(( $(date +%s) - $(stat -c %Y "$done_file") ))

    # 30분(1800초) 이상이면 경보
    if [ "$file_age" -ge 1800 ]; then
        # 이미 경보 보냈는지 체크 (escalated 마커)
        escalated_file="$EVENTS_DIR/${task_id}.done.escalated"
        [ -f "$escalated_file" ] && continue

        log "${task_id}: stale .done 감지 (age=${file_age}s, 30분 초과) → 에스컬레이션"
        source /home/jay/workspace/.env.keys 2>/dev/null || true
        cokacdir --cron "⚠️ ${task_id} 완료 후 ${file_age}초 경과, 아직 미처리. 보고서: memory/reports/${task_id}.md" \
            --at "1m" --chat "$COKACDIR_CHAT_ID" --key "$COKACDIR_KEY_ANU" --once 2>/dev/null || true
        touch "$escalated_file"
    fi
done

# Case 2: 오래된 .done.acked 정리 (24시간 이상 → archive 이동)
for acked_file in $(find "$EVENTS_DIR" -maxdepth 1 -name "*.done.acked" -type f 2>/dev/null); do
    file_age=$(( $(date +%s) - $(stat -c %Y "$acked_file") ))
    if [ "$file_age" -ge 86400 ]; then
        task_id=$(basename "$acked_file" .done.acked)
        ARCHIVE_DIR="$EVENTS_DIR/archive"
        mkdir -p "$ARCHIVE_DIR"
        mv "$acked_file" "$ARCHIVE_DIR/" 2>/dev/null && log "${task_id}: .done.acked → archive (24h 경과)"
        # .done.escalated도 같이 정리
        [ -f "$EVENTS_DIR/${task_id}.done.escalated" ] && mv "$EVENTS_DIR/${task_id}.done.escalated" "$ARCHIVE_DIR/" 2>/dev/null
    fi
done

# heartbeat
echo "$(date -Iseconds)" > /home/jay/workspace/logs/done-watcher.heartbeat
```

#### 제거 대상
- Case 1 (기존): .done.clear archive 이동 → 전체 제거
- Case 2 (기존): L1 실패 보완 notify-completion 호출 → 전체 제거
- Case 3 (기존): .done.notified retry → 전체 제거
- `.done.clear`, `.done.notified` 관련 로직 전체 제거

### 3. whisper-compile.py 확인 및 수정
현재 경로: `/home/jay/workspace/scripts/whisper-compile.py`

- `scan_done_files()` 함수가 `*.done` 파일을 정상 스캔하는지 확인
- `.done.acked`, `.done.escalated` 파일은 제외하는지 확인
- 스캔 결과를 whisper 브리핑에 `[완료] task-X, task-Y` 형식으로 포함하는지 확인
- 현재 "미처리 .done: 0건"으로 나오는 이유 파악 → .done 파일이 너무 빨리 정리되어서였으므로, 이제 .done이 보존되면 정상 작동할 것이지만 로직 검증 필수

### 4. user-prompt-submit.sh 확인
현재 경로: `/home/jay/.claude/hooks/user-prompt-submit.sh`

- whisper-compile.py 호출이 정상 동작하는지 확인
- .done 스캔 결과가 whisper 출력에 포함되는지 확인
- `.done.clear` 관련 스캔 로직이 있다면 제거

### 5. completion-handler-instructions.md 처리
현재 경로: `/home/jay/workspace/scripts/completion-handler-instructions.md`

- 이 파일은 새 아누 세션이 .done.clear를 만드는 지시문 → **더 이상 사용하지 않음**
- 파일 상단에 `# DEPRECATED (2026-03-16): Pull 모델 전환으로 폐기` 주석 추가
- 삭제하지 말 것 (히스토리 보존)

### 6. 기존 .done 잔여 파일 정리
- `memory/events/` 에 남아있는 `.done.notified`, `.done.clear`, `.done.clear2` 파일들 → archive/로 이동
- `.done` 파일은 건드리지 않음 (아누가 처리해야 함)

## 테스트 요구사항

### notify-completion.py 테스트
- 체인 중간 Phase: dispatch.py 직접 호출 동작 확인 (기존 유지)
- 체인 마지막 / 독립 작업: 텔레그램 텍스트만 전송, wake_anu_session 미호출 확인
- .done 파일이 수정/삭제/rename되지 않는지 확인
- .done.notified 파일이 생성되지 않는지 확인

### done-watcher.sh 테스트
- .done 파일 30분 미만: 아무 동작 없음
- .done 파일 30분 이상: 에스컬레이션 알림 1회 전송 + .done.escalated 마커 생성
- .done.escalated 존재 시: 중복 알림 없음
- .done.acked 24시간 이상: archive 이동

### whisper-compile.py 테스트
- .done 파일 존재 시 브리핑에 포함되는지
- .done.acked, .done.escalated 파일은 제외되는지
- .done 파일 0건일 때 "없음"으로 표시되는지

## 참고 파일
- 미팅 기록: `memory/meetings/2026-03-16-done-protocol-redesign.md`
- 현재 코드: `scripts/notify-completion.py`, `scripts/done-watcher.sh`, `scripts/whisper-compile.py`
- 기존 테스트: `scripts/tests/test_done_protocol.py`, `scripts/tests/test_notify_completion.py`, `scripts/tests/test_whisper_compile.py`
- 체인 매니저: `chain_manager.py`

## 절대 금지
- .done 파일을 삭제하거나 rename하는 코드 추가 금지 (아누 전용)
- cokacdir --cron으로 아누 세션 깨우는 코드 추가 금지
- .done.notified, .done.clear 파일 생성 로직 추가 금지
- 체인 중간 Phase의 dispatch.py 직접 호출 로직 변경 금지