---
task_id: task-2405
type: context
scope: task
created: 2026-05-03
updated: 2026-05-03
status: completed
---

# 맥락 노트: task-2405

**task**: task-2405

---

## 결정 근거

### Fix A — `.escalate.acked` 의미 반전 (CRITICAL)
- **현재 코드 (line 200)**: `[[ -f "$esc" && ! -f "$acked" ]]` → acked 발급 시 알람 재개
- **회장 정의**: acked = "회장 인지함 = 알람 그만"
- **결정**: `[[ -f "$esc" || -f "$acked" ]]` → 어느 하나라도 있으면 skip
- **대안 기각**: `[[ -f "$acked" ]]` 단독 체크 — escalate 단독 보호 누락 (NG case 2 미커버)

### Fix B — 완료 인식 자동 박제
- **현재 코드 (line 268)**: `.done`/`.done.acked`/`.done.clear` 체크 후 continue (status는 그대로 running)
- **회장 정의**: 완료 산출물 존재 시 watchdog가 직접 status=escalated 박제 → 영구 검사 제외
- **결정**: line 268-271에 `.done.notified` 체크 추가 + status 박제 추가 (flock 사용, escalated 라인 480 패턴 재사용)
- **대안 기각**: dispatch.py/finish-task.sh에 박제 추가 — 두 파일 forbidden

### Fix C — 후속 task 박제
- **방법 1 (단순)**: `<task>.superseded_by` 마커 파일 존재 시 skip + status=escalated 박제
- **방법 2 (자동)**: 다른 task md의 `## 배경`/`## 진단`/제목에 `<task_id>` 언급 grep
- **결정**: 두 방법 모두 적용. 마커 우선, grep은 보조 (성능: 모든 task md 검사 비용 작음 ~50개 미만)
- **대안 기각**: dispatch.py에 superseded_by 자동 생성 — dispatch.py forbidden

### Fix D — 진행 마커 화이트리스트
- **현재 코드 (line 35-41)**: 이미 5종 적용 (`codex-gate`, `qc-done`, `done.merging`, `pr-creating`, `external-running`)
- **결정**: 코드 변경 없음 (회장 정의 D 이미 충족). 주석에 "회장 정의 D" 명시 추가
- **검증**: 회귀 테스트로 5종 마커 각각 0 알람 확인

### 3 Step Why 검증
- **1st Why**: 왜 이 4 fix가 필요한가?
  → A: 현재 코드는 회장 정의 5 NG case 중 4건을 위반. acked가 알람 재개로 해석되고, .done이 status 박제 안 되며, 후속 task가 원본 박제 안 함.
- **2nd Why**: 왜 surgical fix 1 파일이 최선인가?
  → B: dispatch.py/finish-task.sh/done-watcher.py는 task 명시 forbidden. session-watchdog.sh가 박제 권한을 갖는 것이 아키텍처적으로 정합 (이미 line 478 escalated 박제 패턴 보유).
- **3rd Why**: 왜 박제 권한을 watchdog에 주는 것이 dispatch에 주는 것보다 나은가?
  → C: dispatch는 신규 task 생성/위임이 책임. watchdog는 status 모니터링/판정이 책임. SRP 정합. 또한 watchdog는 2분마다 실행되므로 박제 누락 시 다음 사이클에 자동 복구 (eventual consistency).
- **A-B-C 일관성**: ✅ "회장 NG 5 case → surgical fix 1 파일 → SRP 정합"

## 참조 자료

- 회장 명시 정의: `/home/jay/workspace/memory/tasks/task-2405.md` (line 5-7)
- 이참나 task-2399 fix: `c3fd704c` (이미 D 부분 적용)
- 회장 메모리: `bug_dispatch_after_reboot.md`
- 기존 테스트 패턴: `/home/jay/workspace/tests/test_watchdog_noise_elimination.py` (sed WORKSPACE 치환 블랙박스)
- 현재 escalated task: 2389/2390/2391/2392/2394/2396/2399 (7건, 모두 status=escalated 박제됨)

## 주의사항

- **forbidden 절대 준수**: dispatch.py, scripts/auto_merge.py, scripts/done-watcher.py, scripts/finish-task.sh, scripts/whisper-compile.py 등 21개 파일 수정 금지
- **flock 필수**: status 박제 시 line 474-479 패턴 재사용 (`flock -w 5 200`)
- **grep 위치**: Fix C의 task md grep은 `memory/tasks/*.md`만 대상 (memory/plans/, memory/reports/ 제외 — 성능)
- **DRY_RUN 환경변수**: `WATCHDOG_DRY_RUN=1` 시 알람 전송 skip (이미 line 524 구현됨, L1 검증 시 활용)
- **이참나 fix 위에 추가 보강** — 덮어쓰기 X. line 196 함수 변경 + 진입 필터 추가만.
