# Agent 미팅: 세션 자동 이어가기 Watchdog 시스템 설계

**날짜**: 2026-04-12
**소집 이유**: 팀장 봇 세션이 context limit(200K)으로 종료 시 .done 없이 방치되는 문제의 아키텍처 해결
**참여 페르소나**: 오딘, 토르, 불칸, 야누스, 로키, 헤임달
**미팅 모드**: hybrid
**토론 깊이**: thorough
**총 사이클 수**: 3

---

## Cycle 1 — Independent 라운드

### 아누 분석
dispatch.py는 "fire and forget" 패턴 — cokacdir --cron으로 스케줄링하면 제어권이 넘어감 (dispatch.py:2214). 세션 완료 감지는 .done 파일 polling 기반이나, context limit 종료 시 .done이 생성되지 않아 작업이 방치됨. 설계 방향 3가지 후보: A(dispatch.py 내장), B(별도 데몬), C(cokacdir --on-exit 콜백).

### 페르소나 의견
**오딘**: B안(별도 데몬) 압도적 우위. A안은 dispatch.py(2600줄)에 다른 생명주기(long-running)를 섞는 것이므로 기술 부채. task ID는 서브넘버링 필수(task-1707 → task-1707.2). DA로 "빈도가 월 2-3회면 수동이 나을 수 있다" 지적.

**토르**: subprocess 체인(waitpid) + .done 존재 여부로 3분기 판정. systemd 래퍼 데몬 또는 "while [ ! -f .done ]; do claude --continue; done" 셸 루프 제안.

**불칸**: circuit_breaker 패턴 적용 (task 단위 breaker, threshold=3, 30분 윈도우). 진행률 기반 판단 — 이전 대비 delta 없으면 1회만에 OPEN. 상태 머신: RUNNING→STALLED→RETRYING→COMPLETED/ESCALATED. heartbeat 파일 30초 갱신 제안.

**야누스**: systemd 서비스 정답. inotify로 .done + task-timers.json 감시, CPU 0%, RSS 15-20MB. journalctl 자동 수집. Restart=always로 자기 생존 보장.

**로키**: 보안 위험 5건 식별 — 프롬프트 세탁 공격(HIGH), 무한 재위임(CRITICAL), 파일 변조(MEDIUM), 컨텍스트 인젝션(HIGH), 비용 폭증(HIGH). "사람이 루프 안에 있는 것이 최고 보안 장치."

**헤임달**: 핵심 테스트 케이스 4건. 가장 위험한 레이스 컨디션: .done 작성 직전 crash → watchdog 재위임 → 두 세션 동시 실행. 대안: 팀장 프롬프트에 "80% 시 .partial 생성 후 graceful exit" 규칙.

### 합의/결론
- B안(별도 데몬) 우세하나, 복잡도 우려 강력
- .partial 프로토콜 확장이 유력 대안
- 자동 vs 수동 재위임 트레이드오프 미해결

### 미해결 항목
- watchdog 데몬 vs .partial 프로토콜 — 근본 방향
- 자동 재위임 보안 vs 편의
- 컨텍스트 전달 방식

---

## Cycle 2 — Sequential 심화

### 아누 분석
하이브리드 2레이어 제안: Layer 1(프롬프트 기반 .partial, 75% 도달 시), Layer 2(watchdog 데몬, ungraceful 종료 catch). DA 지정: 오딘. 비관습적 대안: 불칸.

### 페르소나 의견
**토르**: 둘 다 필요. .partial은 ungraceful 종료(30-40%)를 못 잡음. PID 추적은 pgrep 패턴 매칭이 현실적.

**로키**: HMAC 서명으로 .partial 변조 방지. 1회 실패 시 이미 알림 필요. output sanitize 필수. watchdog SPOF는 systemd Restart=always로 해결. 조건부 합격.

### Devil's Advocate (오딘)
**지정**: 오딘
1. **실패 시나리오**: watchdog 오판 → 정상 세션 중인데 재위임 → 두 세션 동시 실행 → 파일 충돌/중복 커밋
2. **후회 이유**: 8팀 전부에 systemd+HMAC+circuit breaker+.partial 적용 → 운영 복잡도 폭발, 장애 시 삼중 의심
3. **더 단순한 대안**: heartbeat + cron 1분 주기. 새 데몬 zero, 새 파일 포맷 zero. YAGNI 원칙.

**반박**: 오딘의 YAGNI 관점 전면 수용. 운영 복잡도 폭발 위험은 현실적. 별도 데몬을 Phase 1에서 제거하고, 기존 cokacdir --cron 인프라만 사용하는 방향으로 설계 수정.
**판정**: 설계 수정 필요 → Cycle 3에서 단순화된 안 합의

### 비관습적 대안 (불칸)
**Dead Man's Switch 역전 모델**: 세션이 매 N초마다 heartbeat 갱신, TTL 만료 시 락 자동 해제. 감시자/판단 주체 없음. 순수 TTL 만료 로직.
1. 최강 지지: 오판 불가능 — 판단 로직이 없고 물리적 TTL 만료만 존재
2. 최강 반론: CPU 스파이크로 정상 세션이 heartbeat 놓치면 살아있는 세션 강제 종료
3. 이상적 시나리오: 세션 수명 짧고, 팀 간 파일 충돌 영역 분리된 환경
4. 노력 수준: 낮음
5. 리스크 등급: 중간

**판정**: 일부 반영 — TTL/heartbeat 개념은 Phase 2 .partial 타이밍에 참고. 전면 채택은 재위임 기능 부재로 기각.
**기각 사유**: 락 해제만으로는 "작업 재개"가 안 됨. 재위임 트리거 기능이 필요.

### 합의/결론
- 별도 데몬 제거, 기존 인프라만 사용
- YAGNI 기반 3단계 접근으로 수정

---

## Cycle 3 — 최종 합의 + Temporal Interrogation

### 아누 분석
오딘 DA 반영하여 설계 대폭 단순화. Phase 1은 dispatch.py --auto-followup + cokacdir --cron 후속 확인만. Phase 2에서 .partial, Phase 3에서 데몬.

### 페르소나 의견
**오딘**: 전면 동의. 20분 고정 followup. --auto-followup 기본값 off. dispatch_task() 함수 말미에 cron 등록. task-timers.json에 retry_count, max_retry, parent_task, task_file 필드 추가.

**로키**: 조건부 합격 — 재위임 전 task-file sha256 checksum 검증 1건 추가 필수 (구현 3줄). 나머지 보안 리스크는 Phase 2로 수용 가능.

**헤임달**: 핵심 테스트 5건 정의. 가장 위험한 레이스 컨디션: followup 실행 시점과 .done 생성 동시 → 재위임 직전 .done 2차 확인으로 해결. 기존 테스트와 호환 (--auto-followup 미전달 시 기존 동작 100% 유지).

### Temporal Interrogation

**[HOUR 1] 작업 시작**
- [RESOLVED] dispatch.py의 dispatch_task() 함수 말미, 텔레그램 발송 직후에 --auto-followup 분기 삽입
- [RESOLVED] followup cron 프롬프트: "task-{id} 상태 확인: .done 파일 → pass, 프로세스 생존 → 대기, 둘 다 없음 → 재위임"
- [RESOLVED] task-timers.json 스키마: retry_count(int, default 0), max_retry(int, default 2), parent_task(str|null), task_file(str) 추가
- [OPEN] followup cron이 어느 봇/채팅에서 실행되는가? → 아누 세션 (동일 chat_id)

**[HOUR 2-3] 핵심 구현**
- [RESOLVED] 프로세스 종료 판단: ps aux | grep task_id + task-timers.json status 필드
- [RESOLVED] 원본 task-file 재사용: task-timers.json의 task_file 필드에 경로 기록, 재위임 시 그대로 참조
- [RESOLVED] --auto-followup 기본값: off (opt-in, 안정성 확인 후 default on 전환 검토)
- [RESOLVED] 재위임 전 task-file checksum 검증 (sha256, 로키 요구)
- [RESOLVED] 재위임 직전 .done 2차 확인 (헤임달 요구)

**[HOUR 4-5] 구현 후반**
- [OPEN] followup 실패 시 에러 핸들링 — 재위임 실패하면 어떻게? → 에스컬레이션 파일 생성
- [RESOLVED] 기존 dispatch.py 테스트와 호환 — --auto-followup 미전달 시 기존 동작 유지

**[HOUR 6+] 마무리**
- [OPEN] 대시보드에서 재위임 이력을 어떻게 표시할 것인가?
- [RESOLVED] 배포: dispatch.py 수정 후 대시보드 서버 재시작

---

## 최종 합의 사항

1. **YAGNI 기반 3단계 접근 채택**
   - Phase 1: dispatch.py --auto-followup (기존 cokacdir --cron 인프라만, 새 데몬 zero)
   - Phase 2: .partial 프로토콜 (팀장 프롬프트 규칙 추가)
   - Phase 3: 전용 watchdog 데몬 (빈도 데이터 축적 후 결정)

2. **Phase 1 상세**
   - dispatch.py에 --auto-followup N 옵션 추가 (N=분, 기본 20분, 기본값 off)
   - 작업 위임 후 N분 후 상태 확인 cron 자동 등록 (cokacdir --cron --once)
   - 상태 확인: .done 있으면 pass, 프로세스 없고 .done 없으면 재위임
   - max_retry = 2, retry_count를 task-timers.json에 기록
   - 서브넘버링: task-1707 → task-1707.2 → task-1707.3
   - 재위임 전: task-file sha256 checksum 검증 + .done 2차 확인
   - 1회 실패 시 알림, 2회 소진 후 에스컬레이션

3. **보안 조건 (로키 합격 조건)**
   - task-file checksum 검증 (sha256)
   - 원본 task-file만 재사용, 이전 output은 참조 전용
   - 일일 재위임 상한 (전역 20회 권장)

4. **테스트 (헤임달 5건)**
   - cron 등록 정확성, .done 존재 시 pass, 재위임+retry_count 기록, max 초과 시 차단, 서브넘버링 무결성

## 미해결 항목
- followup cron이 아누 세션에서 실행되는 방식의 구체적 프롬프트 설계 → 구현 시 결정
- 대시보드 재위임 이력 표시 방식 → Phase 2에서 결정
- followup 실패 시 에스컬레이션 경로 → 구현 시 결정

## 다음 단계

### 합의 사항 → 3문서 매핑 가이드
- Phase 1~3 로드맵, 위임 대상 팀 → 계획서(plan.md)
- YAGNI 결정 근거, DA 반론, 기각된 대안(별도 데몬, Dead Man's Switch) → 맥락노트(context-notes.md)
- Phase 1 구현 항목 → 체크리스트(checklist.md)
