# Agent 미팅: 자기체이닝 인프라 안정성 심층 분석

**날짜**: 2026-03-10
**소집 이유**: task-439.1(5시 자기체이닝 인프라 변경) 이후 4건 장애 연속 발생 — 근본 원인 전수 조사
**참여 페르소나**: 토르(동시성), 불칸(안정성), 아르고스(엣지케이스), 로키(보안), 야누스(DevOps)
**미팅 모드**: hybrid
**토론 깊이**: thorough
**총 사이클 수**: 2

---

## Cycle 1 — Independent 라운드

### 아누 사전 분석

코드 전체를 읽고 8개 구조적 결함을 발견:
1. 체이닝 시스템 이원화 (chain.py vs chain_manager.py)
2. notify-completion.py가 실제 dispatch 미수행
3. .done.clear가 dispatch 전에 생성
4. team_prompts.py 모듈레벨 크래시 잔존
5. chain.py ANU_KEY 하드코딩 잔존
6. WORKFLOW Step 8+9 이중 체인 처리
7. send_telegram_notification이 봇 세션 생성 (토큰 절약 무효화)
8. chain_manager.py check 3회 중복 호출

### 페르소나 의견

**토르 (동시성/파이프라인)**:
- TOP 1 [CRITICAL]: dispatch_next_phase()가 print만 하고 dispatch.py 호출 없음 — 체인 100% 멈춤
- TOP 2 [HIGH]: .done.clear 선생성 후 dispatch 실패 → 복구 불가 half-state
- TOP 3 [MEDIUM-HIGH]: chain.py ANU_KEY 하드코딩 + fcntl vs touch 락 불일치
- 추가: insuwiki-p2p3.lock 파일 방치 = 과거 비정상 종료 증거

**불칸 (안정성/데이터흐름)**:
- TOP 1 [CRITICAL]: "반쪽 체이닝" — chain_manager.py 체인의 중간 Phase는 자동 dispatch 100% 불가
- TOP 2 [HIGH]: .done.clear 선생성 → dispatch 실패 시 재시도 원천 차단
- TOP 3 [MEDIUM]: Step 8 + Step 9 이중 체인 완료 처리 — chain.py task-done이 실질적 dispatch 담당
- 비관습적 대안: .done → .done.clear rename 방식 (POSIX 원자적)

**아르고스 (엣지케이스/QA)**:
- TOP 1 [치명]: dispatch_next_phase()에 dispatch.py 호출 코드 없음 (코드 직접 확인)
- TOP 2 [심각]: chain.py ANU_KEY 하드코딩 + team_prompts.py 모듈레벨 크래시 → 4건 장애의 공통 뿌리
- TOP 3 [중간]: Step 9 중복 dispatch 위험
- ★ 핵심 발견: 4건 장애의 공통 뿌리 2개 — (1) dispatch_next_phase 미구현, (2) ANU_KEY 보안 수정이 기존 경로를 파괴
- 테스트 799개가 통합 시나리오(dispatch 실제 호출, env 미설정 경로)를 커버하지 못함

**로키 (보안)**:
- TOP 1 [CRITICAL]: chain.py 35행 ANU_KEY 하드코딩 "c119085addb0f8b7"
- TOP 2 [CRITICAL]: chain.py _dispatch_phase()의 bash -c 쉘 인젝션 — chain_id/team/level 직접 삽입
- TOP 3 [HIGH]: send_telegram_notification 프롬프트 인젝션 벡터 (chain_id → cokacdir --cron 프롬프트)
- 추가: chains/*.json 파일 권한 664 (그룹 쓰기 가능)
- 근본 원인: DRY 위반 (ANU_KEY 처리가 파일별 독립 구현)

**야누스 (DevOps/운영)**:
- TOP 1 [치명]: 자기체이닝 dispatch 미동작 — 감지 메커니즘 부재 (침묵 장애)
- TOP 2 [심각]: 이중 체이닝 시스템 — Step 8+9 이중 책임, 팀장 구분 불가
- TOP 3 [심각]: 환경변수 미로드 시 비대칭적 침묵 (chain.py는 하드코딩으로 동작, dispatch.py는 크래시)
- 추가: watchdog이 pending-stuck 감지 못함 (running만 체크)
- 추가: 팀장이 Step 4.5~9를 올바르게 수행할 확률이 이미 한계 초과

### Cycle 1 전원 합의 (5/5)

1. **dispatch 실종**: notify-completion.py dispatch_next_phase() 수정 필수 (전원)
2. **chain.py ANU_KEY**: 하드코딩 즉시 제거 (전원)
3. **team_prompts.py**: 모듈레벨 크래시 → lazy evaluation (전원)
4. **이중 체이닝 시스템**: 역할 경계 명문화 또는 통합 (전원)
5. **.done.clear 복구 경로**: dispatch 실패 시 재시도 가능하도록 (4/5)

---

## Cycle 2 — DA 라운드 (아르고스 지정)

### Devil's Advocate 3대 질문

**1. 실패 시나리오:**
- dispatch_next_phase 수정 시 chain_manager.py 락과 dispatch.py의 chain JSON 이중 쓰기 위험
- team_prompts.py lazy evaluation → ANU_KEY 빈 문자열 silent 주입
- .done rename → O_CREAT|O_EXCL 원자적 선점 제거 → 중복 dispatch

**2. 6개월 후 후회:**
- chain_manager.py만 남기면 멀티팀 병렬 Phase 기능 상실 (insuwiki-p2p3 패턴)
- chain.py만 남기면 stalled 감지, watchdog 기능 상실

**3. 더 단순한 대안:**
- "완료 통보 경로를 하나로 통합" — 팀장은 항상 notify-completion.py만 호출

### 비관습적 대안: 이벤트 소싱으로 교체
- 최강 지지: chain JSON 상태 불일치가 모든 버그의 근원. 이벤트 소싱은 상태 불일치 자체가 불가능.
- 최강 반론: 이벤트 재계산 느림, 기존 체인 마이그레이션 필요, 리스크 높음.
- 노력: 높음 (2팀 3주)
- **판정: 기각.** 현재 규모에서 과잉. 구조적 수정으로 충분.

### DA 반박 및 판정

**반론 1 (이중 쓰기)**: 반박 수용. dispatch_next_phase()는 chain_manager.py next subprocess 종료 후 실행 → 시간적 분리로 이중 쓰기 없음. **판정: 반박 수용.**

**반론 2 (silent failure)**: 부분 수용. **설계 수정: 단순 lazy 아닌, _get_anu_key() 패턴으로 import 안전 + 사용 시 fail-fast.** **판정: 설계 수정 반영.**

**반론 3 (.done rename)**: 수용. **합의안 수정: 기존 O_CREAT|O_EXCL 유지 + dispatch 실패 시 .done.clear 삭제로 재시도 허용.** **판정: 합의안 수정.**

---

## 최종 합의 사항

### 즉시 수정 (6개 항목)

1. **notify-completion.py dispatch 실제 구현**: dispatch_next_phase() 결과가 action=dispatch이면 dispatch.py를 실제 subprocess 호출. chain_manager.py next 종료 후 실행 (시간적 분리).

2. **notify-completion.py .done.clear 복구 경로**: dispatch 실패 시 .done.clear 삭제하여 재시도 허용. 기존 O_CREAT|O_EXCL 원자적 선점은 유지.

3. **chain.py ANU_KEY 하드코딩 제거**: 35행 `"c119085addb0f8b7"` → `""`. _cron_notify()에서 키 존재 검증 추가.

4. **chain.py bash -c 쉘 인젝션 수정**: _dispatch_phase()를 subprocess 리스트 방식으로 전환 + chain_id/team/level 화이트리스트 검증.

5. **team_prompts.py 모듈레벨 크래시 제거**: EnvironmentError 삭제 → _get_anu_key() 함수 패턴으로 사용 시점 검증 (import 안전 + 사용 시 fail-fast).

6. **DIRECT-WORKFLOW Step 9 조건 분기**: chain_manager.py 체인이면 Step 9 스킵 규칙 추가.

### 단기 수정 (2개 항목)

7. **watchdog pending-stuck 감지 추가**: chain_manager.py check-stalled에 "active 체인 + pending task + 직전 task done + 30분 경과" 조건 추가.

8. **send_telegram_notification → cokacdir --sendfile 또는 직접 Telegram API**: 봇 세션 생성이 아닌 텍스트만 전송하는 방식으로 전환 (토큰 절약 실효성 확보).

### 중기 결정 (보류)

9. **chain.py와 chain_manager.py 통합 여부**: DA 지적대로 두 시스템의 추상화 레벨이 다름 (멀티팀 병렬 vs 단일팀 순차). 당장 통합은 리스크가 큼. 역할 경계를 명문화하되, 통합은 실전 프로젝트 경험 후 재판단.

---

## 미해결 항목

- insuwiki-p2p3.lock 파일 방치 원인 규명 (과거 비정상 종료 증거)
- chains/*.json 파일 권한 664 → 600 강화
- chain_id/phase_name 입력값 정규화 함수 (프롬프트 인젝션 방어)
- notify-completion.py 통합 테스트 (dispatch 실제 호출 end-to-end)

## 다음 단계

### 합의 사항 → 작업 매핑
- 즉시 수정 6개 → 위임 작업 1건으로 묶어 팀에 dispatch
- 단기 수정 2개 → 별도 작업
- 중기 결정 → 실전 후 재판단
