# task-613.1 완료 보고서: .done 프로토콜 심층 분석 및 근본 수정

**S**: .done 프로토콜은 팀 작업 완료를 아누에게 통보하는 핵심 메커니즘이며, 3-Layer Defense(L1 finish-task, L2 whisper, L3 done-watcher)로 설계되어 있다. task-607.1에서 auto_merge.py의 `.done.clear` 조기 생성 문제를 수정한 바 있다.

**C**: task-609.1, task-611.1 등 완료된 작업의 `.done.clear`가 존재하지만 아누가 감지/보고한 적이 없다. done-watcher 로그에서 task-586.1이 20회, task-589.1이 50회 이상 반복 감지되며 무한 루프가 확인되었다. 근본 원인: (1) notify-completion.py가 아누 인지 전에 `.done.clear` 생성+archive 이동, (2) `.done` 파일을 아무도 제거하지 않아 done-watcher가 무한 반복, (3) archive 이동으로 user-prompt-submit.sh의 `.done.clear` 감지가 무력화.

**Q**: 아누가 반드시 작업 완료를 인지하도록 `.done` 프로토콜의 근본 결함을 수정할 수 있는가?

**A**: 옵션 B(`.done.clear`를 아누 전용으로) 적용하여 4개 파일을 수정. `.done.notified` 중간 상태를 도입하고, `.done.clear`는 아누만 생성하도록 변경. done-watcher를 3-Case 로직(정리/L1보완/재시도)으로 재작성. pytest 98건 전부 PASS (기존 80 + 신규 18), pyright 에러 0건.

---

## 진단 결과 (Phase 1)

### .done 수명주기 전체 경로

#### 기존 (결함 있음)
```
.done (팀 생성)
  → L1: finish-task.sh → notify-completion.py
    → .done.clear 즉시 생성 + archive 이동 (아누 인지 전!)
    → cokacdir --cron 1분 후 아누 깨움
  → L3: done-watcher.sh (30초 폴링)
    → .done.clear 확인 → 없음 (archive로 갔으므로)
    → .done.clear 재생성 → notify-completion.py 호출 → SKIP
    → .done.clear → archive 이동
    → .done 파일은 그대로 → 다음 30초에 또 감지 (무한 루프!)
```

#### 근본 원인 5건

1. **notify-completion.py 조기 `.done.clear` 생성** (라인 257-269): 아누가 보고서를 읽고 처리하기 전에 `.done.clear`를 생성. `.done.clear`의 의미가 "notify 호출됨"과 "아누 인지"로 혼동.

2. **즉시 archive 이동** (라인 263-269): `.done.clear` 생성 직후 archive/로 이동하여 events/에 `.done.clear`가 존재하는 시간이 0에 가까움. user-prompt-submit.sh의 5분 이내 `.done.clear` 스캔이 무력화.

3. **`.done` 파일 미제거**: 어떤 코드 경로에서도 `.done` 파일을 제거하지 않음. `.done.clear`가 "처리 완료" 마커이지만 archive로 가버리므로 done-watcher가 `.done`을 계속 발견.

4. **done-watcher 무한 루프**: `.done.clear` 확인 → 없음 → 생성 → archive → 다음 폴링에서 또 찾음. 로그 증거: task-586.1이 14:12~14:24 동안 20회+ 감지, task-589.1이 17:15~17:46 동안 50회+ 감지.

5. **orchestrator.py `.done`→`.processed` rename**: 코드 존재하나 프로세스 미실행 (ps 확인). 현재 비활성이므로 영향 없음.

### 핵심 질문 답변

1. **task-609.1 끊긴 지점**: finish-task.sh → notify-completion.py → `.done.clear` 생성+archive 이동 → cokacdir --cron 아누 깨움. `.done.clear`가 events/에서 사라져 아누 훅이 감지 불가. cokacdir --cron 1분 후 스케줄은 동작했으나, 아누 세션에서 `.done`도 `.done.clear`도 없는 상태로 보고서만 읽고 조용히 종료한 것으로 추정.

2. **notify-completion.py 라인 257-269**: 의도된 설계 아님. "선점"(중복 처리 방지)과 "통보"(아누 인지)를 `.done.clear` 하나에 혼합한 설계 결함.

3. **user-prompt-submit.sh 라인 60**: archive/ 이동 후 `find`에서 잡히지 않음 (확인됨).

4. **done-watcher + notify-completion 중복 `.done.clear` 생성**: 문제를 악화시킴. done-watcher가 `.done.clear` 생성 → notify-completion SKIP → done-watcher archive 이동 → 다음 폴링에서 반복.

5. **orchestrator.py**: 현재 비활성 (프로세스 미실행). `.done`→`.processed` rename은 발동하지 않음.

---

## 설계 결정 (Phase 2)

### 선택: 옵션 B - `.done.clear`를 아누 전용으로

선택 이유:
- **단순성**: `.done.notified` 마커 하나 추가로 기존 코드 최소 변경
- **신뢰성**: `.done.clear`가 아누 인지를 명확히 의미
- **견고성**: `.done`이 아누 처리 전까지 events/에 유지 → whisper-compile.py, user-prompt-submit.sh가 자연스럽게 감지
- **디버깅**: `.done` → `.done.notified` → `.done.clear` 3단계 추적 가능

### 새 상태 전이
```
.done (팀 생성)
  → .done.notified (notify가 원자적 생성, events/에 유지)
  → cokacdir --cron 아누 깨움
  → [5분 후 미인지 시 done-watcher가 --retry로 재깨움, 최대 3회]
  → .done.clear (아누가 직접 생성)
  → done-watcher가 .done + .done.notified 정리 + .done.clear → archive
```

---

## 구현 내용 (Phase 3)

### 수정 파일 4건 + 신규 파일 1건

1. `/home/jay/workspace/scripts/notify-completion.py` — 핵심 수정
   - `create_done_clear()` 삭제 → `create_done_notified()` 신규
   - main() else 브랜치: `.done.clear` 생성+archive → `.done.notified` 생성
   - main() 체인 중간 브랜치: 동일 변경
   - `--retry` 플래그 추가 (done-watcher 재시도용)
   - `log_protocol()` 함수 추가

2. `/home/jay/workspace/scripts/done-watcher.sh` — 완전 재작성
   - Case 1: `.done.clear` 존재 → `.done`+`.done.notified` 정리 + archive 이동
   - Case 2: `.done`만 존재 (60초+) → notify-completion.py 호출
   - Case 3: `.done.notified` 존재 (5분+) → `--retry`로 아누 재깨움 (최대 3회)

3. `/home/jay/.claude/hooks/user-prompt-submit.sh` — 단순화
   - `.done.clear` 기반 fallback 로직 제거 (`.done`이 유지되므로 불필요)
   - `.done.notified` 존재 여부로 상태 표시 차별화

4. `/home/jay/workspace/scripts/completion-handler-instructions.md` — 정리 지시 추가
   - Step 1에 `.done` 파일, `.done.notified` 파일 제거 지시 추가

5. `/home/jay/workspace/scripts/tests/test_done_protocol.py` — 신규 테스트 18건

---

## 테스트 결과 (Phase 4)

### pytest 전체 결과: 98 passed (0.21s)

- 기존 test_notify_completion.py: 13 passed (회귀 없음)
- 기존 test_whisper_compile.py: 67 passed (회귀 없음)
- 신규 test_done_protocol.py: 18 passed

### 신규 테스트 커버리지

- `TestCreateDoneNotified` (4건): 원자적 생성, 중복 방지, 내용 검증, events/ 유지
- `TestLogProtocol` (3건): 파일 생성, 포맷 검증, 추가 모드
- `TestRetryMode` (3건): retry 시 wake 호출, notified 미생성, chain 미호출
- `TestDoneProtocolIntegration` (4건): 정상 플로우, 체인 중간, 중복 방지, done 보존
- `TestDoneWatcherLogic` (4건): cleanup, archive 이동, notified 스킵, retry 제한

### pyright 결과: 0 errors, 0 warnings, 0 informations

---

## 발견 이슈 및 해결

### 자체 해결 (5건)

1. **done-watcher 무한 루프** — `.done` 미제거 + `.done.clear` archive 이동이 원인. done-watcher를 3-Case 로직으로 재작성하여 `.done.clear` 존재 시 정리 수행.

2. **notify-completion.py 조기 `.done.clear` 생성** — `create_done_clear()` 제거, `create_done_notified()` 도입. `.done.clear`는 아누만 생성.

3. **user-prompt-submit.sh `.done.clear` 감지 실패** — `.done.clear` fallback 로직 제거. `.done`이 유지되므로 `.done` 파일만 체크하면 충분.

4. **completion-handler-instructions.md 정리 지시 누락** — `.done.clear` 생성 후 `.done`과 `.done.notified` 제거 지시 추가.

5. **아누 미인지 시 복구 경로 없음** — done-watcher에 `--retry` 메커니즘 추가 (최대 3회, 5분 간격).

### 범위 외 미해결 (1건)

1. **기존 events/ `.done.clear` 파일 34건 누적** — done-watcher Case 1이 다음 실행 시 자동 정리 예정. 수동 개입 불필요. 정리 후 archive에 합류.

---

## QC 셀프 체크

- [x] 1. 다른 파일 영향: whisper-compile.py(영향 없음, `.done` 스캔 그대로), auto_merge.py(영향 없음, `.done`+`.done.merging` 체크 그대로)
- [x] 2. 엣지 케이스: `.done.notified` 이미 존재 시 중복 방지, retry 3회 초과 시 에스컬레이션, archive 이동 실패 시 graceful 처리
- [x] 3. 작업 지시 일치: 5개 근본 원인 규명, 옵션 선택, 구현, 로깅, 테스트 모두 수행
- [x] 4. 에러 처리: O_EXCL 원자적 생성, OSError graceful 처리, 타임아웃 처리
- [x] 5. 테스트 커버리지: 단위(11건) + 통합(4건) + done-watcher 로직(4건) = 18건 신규
- [x] 6. 발견 이슈 직접 해결: 5건 해결, 1건 범위 외(자동 정리 예정)

---

## 마아트 독립 검증 결과

### 판정: PASS (이슈 수정 후)

**발견 이슈 및 조치:**

1. **(MEDIUM) 보고서 수치 오류** — test_notify_completion.py 실제 13건을 16건으로 기재, test_whisper_compile.py 실제 67건을 64건으로 기재. → 수정 완료
2. **(LOW) test_prompt_length_under_120_chars 오도성 이름** — 함수명이 120자 암시하나 실제 500자 검증. → `test_prompt_length_under_500_chars`로 수정
3. **(LOW) test_instructions에 done.notified 어설션 누락** — completion-handler-instructions.md의 `.done.notified` 정리 지시를 검증하는 어설션 없음. → 어설션 추가
4. **(LOW) done-watcher.sh Case 3 mtime 갱신** — retries 업데이트 시 `open('w')`로 mtime 갱신됨. 의도된 동작(5분 간격 재시도)에 부합하나 주석 없음. → 의도된 동작으로 판단, 수정 불필요
5. **(BLOCKER) task-613.1.done 미생성** — 워크플로우상 finish-task.sh는 QC 이후 마지막에 호출. 정상.

**검증 증거:**
- pytest 98 passed (직접 재실행)
- pyright 0 errors (직접 실행)
- 코드 직접 검토: `.done.clear` 생성 코드 완전 제거 확인
- done-watcher.sh 3-Case 로직 코드 직접 확인
