# Watchdog 노이즈 제거 — 5건 false alert 근본 fix ★ Lv.3 critical

## 작업 레벨: Lv.3 critical (회장 강한 명시 승인)

## 회장 명시
2026-05-03 "요즘 와치독 발생 작업할 때마다 나타난다. 심층분석해서 개선해! 개판칠거면 하지마"

## 진단 (아누 사전 분석 — 재현 완료)

### 버그 #1 — `no-taskfile` false positive (CRITICAL)
**증상**:
```
[2026-05-03 08:04:03] task-2389: task_file 없음 (memory/tasks/task-2389.md), 재위임 불가
```
**실제**:
```
$ ls -la memory/tasks/task-2389.md
-rw-rw-r-- 1 jay jay 8192 May  3 07:17 memory/tasks/task-2389.md  ← 존재
```
**원인 후보** (코드 분석 의무):
- 경로 상대/절대 혼선 (cwd 의존?)
- stat 또는 -f 검사 로직 결함
- task_id에서 task_file 매핑 함수 결함
- 위치: `scripts/session-watchdog.sh:339` 부근

### 버그 #2 — 동시 알람 = 노이즈 2배
**증상**: 같은 task에 `stalled-alert-only` + `no-taskfile` **둘 다** STALLED_LIST에 push → 4건처럼 보임 (실 2 task × 2 알람).
**위치**: `scripts/session-watchdog.sh:261`(stalled-alert-only) + `:339`(no-taskfile)
**fix 방향**: 한 task = 한 알람. no-taskfile은 stalled-alert-only의 sub-cause로 통합.

### 버그 #3 — `.escalate` 마커 무시 → 매 사이클 반복 알람
**증상**: task-2389는 07:41에 `.escalate` 발급. 그러나 watchdog이 매 2분 사이클마다 동일 task에 알람 (07:54, 07:56, 08:04 모두 동일 4건).
**fix**: `memory/events/<task_id>.escalate` 존재 시 알람 억제. `.escalate.acked` 마커는 회장 명시 승인 시점에만 정상 처리 재개.

### 버그 #4 — heartbeat 10분 기준 design 작업에 부적합
**증상**: design팀은 satori 다중 렌더 + L1 스모크 = 봇 컨텍스트 짧게 끊김. heartbeat 즉시 노후 → false stalled.
**fix 방향**:
- 작업 종류별 heartbeat 차등 (design = 30분, code = 10분)
- 또는 봇 G1/G2/G3 게이트 통과 시점에 heartbeat 강제 갱신

### 버그 #5 — 봇 점유 stale 표시 (whisper-briefing)
**증상**: bot-c (task-2389 종료 23분), bot-d (task-2391 종료 27분) 실제 free인데 whisper-briefing이 "봇점유" 표시. dispatch.py 봇 충돌 검사도 stale 점유 판정.
**fix 방향**: `memory/state/bot_status*.json` 또는 `bot_status_resolver` 로직과 협조하여 PID 종료 + heartbeat 노후 시점에 자동 해제 또는 watchdog이 resolver 호출.

## 작업 범위

### Fix 1 — 버그 #1 (`no-taskfile` false positive) 근본 원인 + fix
- `scripts/session-watchdog.sh` 339 부근 task_file 존재 검사 로직 디버그
- 원인 후보 5개 모두 검증 (경로/stat/매핑/cwd/symlink)
- fix 후 회귀 테스트: 실 task md 8개 (task-2389~2396) 모두 watchdog이 "있음"으로 인식 검증

### Fix 2 — 동시 알람 통합 (한 task = 한 알람)
- `STALLED_LIST` 중복 push 방지
- no-taskfile은 stalled-alert-only의 reason 필드로 통합

### Fix 3 — `.escalate` 마커 시 알람 억제
- `memory/events/<task_id>.escalate` 존재 시 watchdog 사이클에서 skip
- `.escalate.acked` 마커가 있으면 정상 처리 재개
- **자동 acked 금지** (회장 승인만 .escalate.acked 생성 가능)

### Fix 4 — heartbeat 차등 + 작업 종류 인식
- `memory/tasks/task-XXXX.md` frontmatter 또는 metadata에서 작업 종류 추출
- design 작업: 30분 stale 기준
- code 작업: 10분 stale 기준 (기존 유지)
- 작업 종류 명시 부재 시 보수적 30분 적용

### Fix 5 — 알람 텔레그램 본문 디버깅 정보 추가
- 알람 텔레그램 보고 시 본문에 "task_file 존재함: yes/no" + "escalate 상태: yes/no" + "heartbeat last: <ts>" 포함

## 회귀 테스트 (12+ 시나리오)
**파일**: `tests/test_watchdog_noise_elimination.py` (신규)

1. 실 task-2389~2396 task md 8개 모두 "task_file 존재" 인식
2. 동시 알람 push 차단 (mock)
3. .escalate 마커 시 알람 skip
4. .escalate.acked 시 정상 처리 재개
5. design heartbeat 30분 차등
6. code heartbeat 10분 유지
7. heartbeat 노후 + .escalate 부재 + task_file 존재 → 정상 stalled-alert-only
8. heartbeat 노후 + .escalate 존재 → skip
9. 알람 텔레그램 본문에 reason + escalate 상태 + heartbeat last 포함
10. 4건 false alert 시나리오 재현 → fix 후 0건 확인 (regression)
11. STALLED_LIST 중복 push 차단 (단위 테스트)
12. 기존 `tests/test_session_watchdog.py` + `tests/test_session_watchdog.sh` 회귀 0

## 검증 시나리오 (회장 명시 4 목표 #1 무오류)
1. 12+/PASS (pytest + bash test)
2. **L1 실 운영 검증**: watchdog 사이클 30분 모니터링 → false alert 0건 확인
3. 회귀 0: dispatch.py / finish-task.sh / done-watcher.py / scripts/auto_e2e_gate.py 무수정
4. mypy/pyright 0 + shellcheck 0
5. 보고서에 4 버그별 fix 매트릭스 + L1 30분 모니터링 결과 의무

## affected_files

### 수정 (1개)
- `scripts/session-watchdog.sh`

### 신규 (2개)
- `tests/test_watchdog_noise_elimination.py`
- `memory/reports/task-XXXX-watchdog-noise.md`

### 변경 금지
- `dispatch.py`, `scripts/auto_merge.py`, `scripts/done-watcher.py`, `scripts/finish-task.sh`
- `scripts/whisper-compile.py`, `scripts/bot_status_resolver.py`
- `scripts/worktree_manager.py`, `scripts/cleanup_stale_task_counter.py`
- `scripts/auto_e2e_gate.py`, `scripts/motion_render_queue.py`, `scripts/ids_phase_monitor.py`
- `scripts/session_watchdog.py`, `scripts/orphan-watchdog.py`, `scripts/bot-status-watchdog.py`
- `skills/**`, `resources/design-md/**`
- `teams/shared/**`, `CLAUDE.md`
- `memory/capabilities/**`, `memory/audit/**`, `memory/state/**`, `.github/**`
- `memory/events/**` (90일 미만)

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "scripts/session-watchdog.sh"
    - "tests/test_watchdog_noise_elimination.py"
    - "memory/plans/tasks/task-XXXX/**"
    - "memory/reports/task-XXXX-watchdog-noise.md"
  forbidden_paths:
    - "dispatch.py"
    - "scripts/auto_merge.py"
    - "scripts/done-watcher.py"
    - "scripts/finish-task.sh"
    - "scripts/whisper-compile.py"
    - "scripts/bot_status_resolver.py"
    - "scripts/worktree_manager.py"
    - "scripts/cleanup_stale_task_counter.py"
    - "scripts/auto_e2e_gate.py"
    - "scripts/motion_render_queue.py"
    - "scripts/ids_phase_monitor.py"
    - "scripts/session_watchdog.py"
    - "scripts/orphan-watchdog.py"
    - "scripts/bot-status-watchdog.py"
    - "scripts/ids_natural_routing.py"
    - "skills/**"
    - "resources/design-md/**"
    - "teams/shared/**"
    - "CLAUDE.md"
    - "memory/capabilities/**"
    - "memory/audit/**"
    - "memory/state/**"
    - ".github/**"
  commands:
    - "pytest"
    - "bash"
    - "shellcheck"
    - "python3"
    - "git log"
    - "git diff"
    - "ls"
    - "stat"
    - "test"
  merge_policy: "tiered"
  ttl_hours: 24
```

## 작업 원칙
- **Think Before Coding**: 버그 #1 root cause부터 디버그 (코드 fix 전). 5 후보 검증 후 가장 가능성 높은 원인 명시.
- **3 Step Why**:
  - 1st Why: 왜 task md 존재인데 "없음" 판정? → 스크립트 검사 로직
  - 2nd Why: 왜 그 로직이 깨졌나? → 경로/stat/매핑/cwd/symlink 중 어느 것?
  - 3rd Why: 왜 회귀 테스트가 잡지 못했나? → 기존 테스트 커버리지 부족
- **Surgical**: session-watchdog.sh 1개 파일만 수정. 다른 watchdog 스크립트(session_watchdog.py, orphan-watchdog.py, bot-status-watchdog.py) 미수정.
- **Goal-Driven**: 4건 false alert → 0건. L1 30분 모니터링 통과.
- **No tokens waste**: 코드 1개 + 테스트 1개 + 보고서 1개. 신규 디렉토리 X.
- **재발 방지**: 회귀 테스트 12개로 5가지 버그 모두 카바.

## 운영
- ★ Lv.3 critical (회장 강한 명시: "개판칠거면 하지마")
- TTL 24h
- 위임: dev2-team (오딘, E2E 게이트 컨텍스트, bot-c)
- finish-task.sh 누락 금지

## 참조
- 회장 명시 2026-05-03 "심층분석해서 개선해! 개판칠거면 하지마"
- 기존 watchdog 작업 이력: `memory/meetings/2026-04-12-session-watchdog-v2.md`
- 회장 메모리 `bug_dispatch_after_reboot.md`
- 회장 4 목표 #1 무오류 (시스템 인프라 직접)