---
task_id: task-2422
type: plan
scope: task
created: 2026-05-03
updated: 2026-05-03
status: completed
---

# 계획서: task-2422 — Watchdog alert 전용화 + 신호등 봇 실 PID 종합 판정

**task**: task-2422
**목표**: watchdog의 timer.json 변경 권한을 제거하고, 신호등(dashboard)이 status 단독이 아닌 3 신호(status + heartbeat + PID) 종합으로 봇 살아있음을 판정
**승인**: 회장 2026-05-03 "와치독은 스스로 아무것도 변경하지 못해야 한다 + 신호등은 실제로 봇이 돌고 있는 것까지 파악해서 최종 결정할 것"
**근거**: task-2414/2417/2420 false positive 박제 사고 (watchdog → status=escalated → 신호등 유휴 → 회장 혼란)

---

## 목표

1. **Fix A**: `scripts/session-watchdog.sh`의 모든 변경 행위 제거 (jq박제 3개소 + 백오프 파일 + timer end 호출). watchdog = read-only + Telegram alert만.
2. **Fix B**: `dashboard/data_loader.py`의 `get_running_tasks_by_team()`이 3 신호(status + heartbeat mtime + 봇 PID) 종합 판정으로 봇 작업중 표시. `status=escalated` 박제에 휘둘리지 않음.
3. **Fix C**: 회귀 테스트 12+ (watchdog 무변경 + 신호등 PID 종합 + task-2414/2417/2420 사고 시나리오 재현).

## 범위

### 포함
- `scripts/session-watchdog.sh` 변경 코드 제거 (jq박제 3개소, backoff 파일 쓰기, task-timer end 호출)
- `dashboard/data_loader.py`의 봇 작업 판정 로직에 heartbeat + PID 체크 추가
- pytest 12+ (watchdog 무변경 + 신호등 PID + 사고 시나리오 재현)
- shellcheck + bash -n + python3 import 검증

### 제외 (다음 페이즈 이후)
- 다른 watchdog 변종 (autocomplete, queue 등)
- bot status API 신규 구축 (현재는 pgrep으로 충분)
- 신호등 UI 컴포넌트 변경 (server.py / 프론트는 본 task 외)

## 위임 계획

- Phase 2 Fix A (watchdog 무변경): **토르(백엔드)** — shell script 가공
- Phase 3 Fix B (data_loader 3 신호): **토르(백엔드)** — Python 로직 재작성
- Phase 4 Fix C (테스트): **헤임달(테스터)** — pytest 12+ 작성
- 통합/Codex 검증/마아트 검증: **오딘(팀장)** 직접

## 검증 기준

- pytest 12+/PASS: `cd /home/jay/workspace && pytest tests/test_watchdog_alert_only.py tests/dashboard/test_signal_pid_aggregation.py -v` → 12 passed
- watchdog timer.json 무변경: `bash scripts/session-watchdog.sh` 실행 후 timer.json mtime 동일
- shellcheck 0: `shellcheck scripts/session-watchdog.sh` → no warnings
- bash -n 0: `bash -n scripts/session-watchdog.sh` → exit 0
- Python import 0: `python3 -c "import dashboard.data_loader"` → exit 0
- L1 스모크: timer.json `status=escalated` 인 task에 fresh heartbeat 두면 dashboard `get_running_tasks_by_team`이 해당 task 포함

## 3 Step Why

1st Why: 왜 이 설계가 필요한가? → A: watchdog이 status=escalated 박제 → 신호등이 status만 보고 유휴 표시 → false positive 사고 반복 → 회장 명시 분리 요구
2nd Why: 왜 A가 최선의 접근인가? → B: 결합도 0이 본질 해결책. status가 하나의 박제 채널이 되면 어떤 alert도 부작용 위험 — 신호 채널을 분리해야 한 채널 박제가 다른 채널을 오염시키지 않음
3rd Why: 왜 B가 다른 대안보다 나은가? → C: 대안 1) status 박제 종류 추가(escalated2 등) — 결합 유지로 동일 문제 재발. 대안 2) watchdog 폐지 — alert 기능 자체 손실. C는 alert 유지 + 결합 제거 양립.
