# .done 프로토콜 심층 분석 및 근본 수정

## 배경
.done 프로토콜은 팀 작업 완료를 아누(오케스트레이터)에게 통보하는 핵심 메커니즘이다.
팀이 작업을 마치면 `memory/events/<task_id>.done` 파일을 생성하고, 아누가 이를 감지하여
보고서를 읽고, 제이회장님께 보고한 뒤, `.done.clear`로 rename하는 것이 정상 흐름이다.

**현재 문제**: task-609.1, task-611.1 등 완료된 작업의 `.done.clear`가 이미 존재하지만,
아누가 감지하거나 보고한 적이 없다. 이전 수정(task-607.1)에서 auto_merge.py의 `.done.clear`
조기 생성 문제를 고쳤지만, 근본 원인이 여전히 남아 있다.

---

## 작업 목표
1. .done 파일의 **전체 수명주기(lifecycle)** 완전 추적
2. .done 파일을 건드리는 **모든 코드 경로** 식별 및 문서화
3. 아누에게 통보 없이 `.done.clear`로 변환되는 **근본 원인** 규명
4. **경쟁 조건(race condition)** 또는 **타이밍 이슈** 확인
5. 아누가 반드시 통보받도록 **견고한 수정** 구현
6. 디버깅용 **로깅/알림** 강화
7. 수정 검증용 **테스트** 작성

---

## 조사 대상 파일 (모두 꼼꼼히 읽을 것)

### 핵심 파일 (직접 .done 파일을 생성/수정/삭제하는 코드)
| # | 파일 | 역할 | .done 관련 동작 |
|---|------|------|-----------------|
| 1 | `/home/jay/workspace/scripts/finish-task.sh` | L1: 팀 작업 완료 시 호출 | `.done` 원자적 생성 + notify-completion.py 호출 |
| 2 | `/home/jay/workspace/scripts/notify-completion.py` | L1: 아누 세션 깨움 | **`.done.clear` 원자적 생성 + archive 이동** + cokacdir로 아누 깨움 |
| 3 | `/home/jay/workspace/scripts/done-watcher.sh` | L3: systemd timer (30초 간격) | 60초 이상 된 `.done` → `.done.clear` 생성 + notify-completion.py 호출 |
| 4 | `/home/jay/workspace/scripts/auto_merge.py` | 자동 머지 | `.done.merging` 선점 (task-607.1에서 수정됨) |
| 5 | `/home/jay/workspace/scripts/whisper-compile.py` | 위스퍼 브리핑 | `scan_done_files()` — `.done` 스캔하여 브리핑에 포함 |
| 6 | `/home/jay/.claude/hooks/user-prompt-submit.sh` | 아누 훅 | whisper-compile.py 호출 + 직접 `.done`/`.done.clear` 파일 감지 |
| 7 | `/home/jay/workspace/orchestrator.py` | 오케스트레이터 (비활성?) | `.done` → `.processed` rename |
| 8 | `/home/jay/workspace/scripts/completion-handler-instructions.md` | 아누 완료 처리 지시문 | `.done.clear` 생성 지시 포함 |

### 관련 설정
| # | 파일 | 역할 |
|---|------|------|
| 9 | `/home/jay/.config/systemd/user/done-watcher.service` | systemd 서비스 정의 |
| 10 | `/home/jay/.config/systemd/user/done-watcher.timer` | 30초 폴링 타이머 |
| 11 | `/home/jay/.claude/hooks/lib/detect-bot.sh` | 봇 식별 (anu/dev1/dev2/dev3) |
| 12 | `/home/jay/workspace/prompts/team_prompts.py` | 팀 프롬프트에 finish-task.sh 호출 지시 포함 |

### 로그 및 상태 파일
| # | 파일 | 내용 |
|---|------|------|
| 13 | `/home/jay/workspace/logs/done-watcher.log` | done-watcher 실행 로그 |
| 14 | `/home/jay/workspace/logs/done-watcher.heartbeat` | 마지막 실행 시각 |
| 15 | `/home/jay/workspace/memory/whisper/status.json` | 위스퍼 마지막 실행 상태 |
| 16 | `/home/jay/workspace/memory/events/.reported/` | 보고 완료 마커 디렉토리 |
| 17 | `/home/jay/workspace/memory/events/archive/` | `.done.clear` 아카이브 |

---

## 이미 발견된 핵심 문제점 (조사 시작점)

### 문제 1: notify-completion.py가 아누 감지 전에 `.done.clear`를 생성
- `finish-task.sh`가 `.done` 생성 직후 `notify-completion.py`를 호출
- `notify-completion.py`의 `main()` 라인 253~278: **`.done.clear`를 원자적으로 즉시 생성** + archive로 이동
- `.done.clear`가 생성되면 `whisper-compile.py`의 `scan_done_files()`가 더 이상 해당 `.done`을 감지하지 못함
- 그런데 archive로 이동까지 되면 **`.done.clear` 파일 자체도 events/ 디렉토리에서 사라짐**
- 결과: 아누의 user-prompt-submit 훅이 실행될 때 `.done`도 `.done.clear`도 events/에 없는 상태

### 문제 2: done-watcher.sh도 동일한 패턴
- 라인 19~27: `.done.clear` 원자적 생성
- 라인 30: `notify-completion.py` 호출 → 이것이 **다시** `.done.clear` 생성 시도 (이미 존재하므로 SKIP)
- 라인 33~35: `.done.clear` → archive 이동
- 로그 증거: task-609.1, task-611.1 모두 `L3 감지 → SKIP (이미 처리됨)` — done-watcher가 감지했으나 이미 L1이 처리한 후

### 문제 3: user-prompt-submit.sh의 `.done.clear` 감지 로직 불완전
- 라인 60: 최근 5분 이내 `.done.clear` 감지 시도
- 그러나 notify-completion.py가 `.done.clear`를 archive/로 즉시 이동시키므로 **events/ 디렉토리에 `.done.clear`가 존재하는 시간이 거의 0**
- `.reported/` 마커 디렉토리로 추적 시도하지만, `.done.clear` 자체가 없으면 `find`에서 잡히지 않음

### 문제 4: cokacdir --cron 아누 세션 깨우기의 신뢰성 불명
- `notify-completion.py`의 `wake_anu_session()`이 `cokacdir --cron`으로 1분 후 아누를 깨움
- 이 깨우기가 실제로 동작하는지? 아누 세션이 이미 활성 상태일 때는?
- cokacdir 크론이 실패해도 retry 없음
- `.done.clear`는 이미 생성+아카이브 완료 → 깨우기 실패 시 복구 경로 없음

### 문제 5: 아키텍처 설계 결함 — "선점"과 "통보"의 분리 실패
- 현재 설계: `.done.clear` 생성 = 선점(중복 처리 방지) = 아누 통보 완료로 간주
- 실제 의미: `.done.clear` 생성 = notify-completion.py가 **호출됨** (아누가 **인지했다는 보장 없음**)
- 아누가 인지하려면: (a) cokacdir 크론이 동작해서 아누 세션 깨워야 하고, (b) 아누 세션이 보고서를 읽고 제이회장님께 보고해야 함
- `.done.clear` 생성 시점과 아누 인지 시점 사이에 **보장되지 않는 갭**이 존재

---

## 수행할 작업

### Phase 1: 진단 (코드 읽기 + 로그 분석)

#### 1-1. 전체 .done 수명주기 문서화
- 위 파일 #1~#8을 모두 읽고, `.done` 파일이 생성 → 감지 → 처리 → `.done.clear` 변환되는 **모든 경로**를 플로우차트 형태로 문서화
- 특히 **경쟁 경로(race path)**를 찾아라:
  - finish-task.sh의 notify-completion.py vs done-watcher.sh의 notify-completion.py
  - notify-completion.py의 `.done.clear` 생성 vs whisper-compile.py의 `.done` 스캔
  - cokacdir --cron 깨우기 vs 아누 훅(user-prompt-submit)의 감지

#### 1-2. 실패 사례 재현
- task-609.1의 시간대별 흐름 추적:
  - `.done` 생성 시각: 확인 필요
  - `.done.clear` 생성 시각: 09:30 (events/ 파일 타임스탬프)
  - done-watcher.log에서 task-609.1 감지 시각: 09:31:20 (이미 SKIP)
  - 아누 세션 활성 여부: whisper status.json 확인
- task-611.1도 동일하게 추적

#### 1-3. cokacdir --cron 동작 확인
- `cokacdir --cron` 명령의 로그가 어디에 쌓이는지 확인
- task-609.1, task-611.1에 대해 실제로 아누 세션이 깨워졌는지 확인
- 깨워졌다면 아누 세션이 어떤 응답을 했는지 확인

### Phase 2: 근본 수정 설계

핵심 원칙: **아누가 인지하지 않은 .done을 .done.clear로 변환하면 안 된다**

#### 설계 옵션 (검토 후 최적안 선택):

**옵션 A: `.done.ack` 중간 상태 도입**
```
.done (팀 생성) → .done.notified (notify-completion이 아누 깨움) → .done.ack (아누가 실제 인지) → .done.clear (아누가 보고 완료)
```
- notify-completion.py: `.done` → `.done.notified`로 rename (`.done.clear` 생성 안 함)
- user-prompt-submit.sh: `.done.notified` 감지 → 아누에게 알림
- 아누가 보고 완료 후 직접 `.done.clear`로 rename

**옵션 B: `.done.clear` 생성을 아누 전용으로**
```
.done (팀 생성) → notify-completion이 아누 깨움 (파일 안 건드림) → 아누가 .done 읽고 보고 → 아누가 .done.clear로 rename
```
- notify-completion.py에서 `.done.clear` 생성 로직 **완전 제거**
- done-watcher.sh에서도 `.done.clear` 생성 **제거** (notify만 재호출)
- 중복 notify 방지: `.done` 파일 내부에 `notified_at` 필드 추가하거나 `.done.notifying` 락 파일 사용

**옵션 C: 이벤트 큐 기반**
```
.done (팀 생성) → notify-completion이 event-queue.py에 등록 → 아누가 큐에서 소비 → .done.clear
```

#### 선택 기준
- **단순성**: 기존 코드 변경 최소화
- **신뢰성**: 아누 인지 보장
- **견고성**: 프로세스 크래시/재시작에도 안전
- **디버깅**: 상태 전이 추적 가능

### Phase 3: 구현

#### 3-1. 선택된 옵션 구현
수정 대상 파일 (옵션에 따라 다름):
- `/home/jay/workspace/scripts/notify-completion.py`
- `/home/jay/workspace/scripts/done-watcher.sh`
- `/home/jay/.claude/hooks/user-prompt-submit.sh`
- `/home/jay/workspace/scripts/whisper-compile.py` (필요 시)
- `/home/jay/workspace/scripts/completion-handler-instructions.md` (필요 시)

#### 3-2. 로깅 강화
- 모든 `.done` 상태 전이에 로그 기록
- 로그 위치: `/home/jay/workspace/logs/done-protocol.log`
- 로그 포맷: `[ISO8601] [ACTOR] task_id: old_state → new_state (reason)`
  - ACTOR: finish-task | notify-completion | done-watcher | whisper | anu-hook | anu-session
- 누락 감지 알림: `.done`이 생성 후 5분 이내에 아누가 인지하지 못하면 경고 로그

#### 3-3. 안전장치
- `.done` 파일에 생성 시각 기록 (이미 있음: `completed_at`)
- notify 실패 시 `.done` 파일 보존 (현재 일부 경로에서 삭제/이동됨)
- done-watcher가 백업 안전망 역할 유지 (아누 깨우기 재시도)

### Phase 4: 테스트

#### 4-1. 단위 테스트
- `notify-completion.py`의 수정된 로직 테스트
- `whisper-compile.py`의 `.done` 스캔 로직 테스트
- `done-watcher.sh`의 수정된 로직 테스트

#### 4-2. 통합 테스트 시나리오
1. **정상 플로우**: `.done` 생성 → 아누 감지 → 보고 → `.done.clear`
2. **경쟁 조건**: `.done` 생성 직후 아누 훅 실행 vs notify-completion.py 실행
3. **아누 비활성**: `.done` 생성 → notify 실패 → done-watcher가 재시도 → 아누 감지
4. **중복 처리 방지**: 같은 `.done`에 대해 여러 actor가 동시 접근
5. **체인 작업**: 중간 Phase `.done` → 다음 Phase 자동 위임 (아누 미깨움) + 마지막 Phase `.done` → 아누 깨움

#### 4-3. 회귀 테스트
- 기존 테스트 전부 통과 확인: `pytest /home/jay/workspace/scripts/tests/`
- 기존 테스트: `test_whisper_compile.py`, `test_notify_completion.py`

---

## 핵심 질문 (반드시 답을 찾을 것)

1. **task-609.1**: finish-task.sh → notify-completion.py → `.done.clear` 생성 + archive 이동 → cokacdir --cron 아누 깨우기. 이 중 어디서 끊겼는가?
2. **notify-completion.py 라인 257~269**: `.done.clear` 생성 + archive 이동이 아누 인지 **전에** 실행됨. 이것이 의도된 설계인가?
3. **user-prompt-submit.sh 라인 60**: `find ... -name "*.done.clear" -newermt "5 minutes ago"`가 archive/ 이동 후에도 동작하는가? (답: 아니다. events/에서 사라졌으므로 find에서 못 잡음)
4. **done-watcher.sh**: notify-completion.py를 호출하는데, notify-completion.py가 **또** `.done.clear`를 생성한다. done-watcher 자체도 `.done.clear`를 생성한다. 이 중복 생성 구조가 문제를 악화시키는가?
5. **orchestrator.py의 `.done` → `.processed` rename**: 이 코드가 현재 활성화되어 있는가? 활성화되어 있다면 `.done` 파일이 `.processed`로 바뀌어 다른 모든 감지 로직을 무력화할 수 있다.

---

## 보고서 경로
`/home/jay/workspace/memory/reports/done-protocol-deep-analysis.md`

## 주의사항
- **직접 수정 전에 반드시 진단 결과를 보고서에 기록**
- 수정 시 기존 `.done.clear` 파일들의 호환성 유지
- 체인 작업(chain_manager.py)의 중간 Phase 처리 로직은 건드리지 않되, 마지막 Phase의 아누 통보는 반드시 보장
- auto_merge.py의 `.done.merging` 로직(task-607.1 수정분)과의 호환성 확인
- 모든 수정은 `/home/jay/workspace/` 하위에만. 훅 파일(`/home/jay/.claude/hooks/`)도 수정 대상에 포함