# 에이전트 미팅 기록: 자동화 오케스트레이터 설계
> task-899.1 | 2026-03-24 | 4 사이클 완료 | **만장일치 합의**

## 참석자
- **오딘 (2팀장)** — 미팅 주관, 아키텍처 설계 판단
- **로키 (보안팀장)** — DA, 보안/권한/충돌 리스크 제기
- **펜리르 (보안팀원)** — DA 보조, 침투/악용 시나리오 제기
- **야누스 (DevOps센터)** — 인프라/데몬/서비스 관점

---

## 사이클 1: 개별 제안 (방안 제시 + 유스케이스별 적합도)

### 오딘 제안 — 아키텍처 원안
- `auto_orch.py` — 30초 주기 cron-polled 이벤트 루프 데몬
- YAML 파이프라인 정의, `/home/jay/workspace/pipelines/`에 저장
- 아누와 **독립 피어** 관계 (하위 아니고 대체도 아님)
- `chain.py` + `dispatch.py` 무수정 래퍼 방식 통합
- 3종 트리거: 이벤트(.done), 스케줄(cron), 수동(--run)
- 파일 기반 컨텍스트 인젝션 (reports/{task_id}.md → 다음 스텝 입력)
- 토큰 비용: 오케스트레이션 자체 0토큰 (Claude 세션 미사용)

### 야누스 제안 — 인프라 설계
- `orchestrator-tick.py` — 5초 주기 systemd oneshot 타이머
- **Stateless tick 패턴**: 상태는 JSON 파일, 프로세스는 매 tick 종료/재시작
- `state/active/`, `state/completed/`, `state/failed/` 디렉토리 분리
- 파일 기반 세마포(locks/), 그레이스풀 셧다운(.shutdown-requested 플래그)
- dispatch.py subprocess 격리 호출 (import 대신 격리 우선)
- 추가 코드 ~400 LOC 예상

### 로키 제기 — 10대 위험
1. **RISK-01 CRITICAL**: Anu-자동화 에이전트 동시 디스패치 경쟁 (task-timers.json 타임윈도우)
2. **RISK-02 CRITICAL**: CEO 승인 게이트 우회 (비즈니스 레벨 gate 부재)
3. **RISK-03 HIGH**: 파이프라인 무한루프 (DAG 미검증)
4. **RISK-04 HIGH**: 토큰 예산 소진 (일일 한도 없음)
5. **RISK-05 HIGH**: 스텝 간 데이터 검증 부재
6. **RISK-06 CRITICAL**: QC/보안 리뷰 게이트 우회
7. **RISK-07 HIGH**: 버그 하나로 전팀 마비 (블래스트 반경)
8. **RISK-08 HIGH**: .done TOCTOU (5+개 소비자 경쟁)
9. **RISK-09 CRITICAL**: 파이프라인 설정에 시크릿 노출
10. **RISK-10 HIGH**: 멀티팀 자동 실행 롤백 불가

로키 최소 보안 기준선 (MVP 전 필수):
1. 팀별 뮤텍스
2. YAML gate 필드 필수
3. DAG 검증
4. 일일 토큰 한도
5. 시크릿 분리
6. 단일 .done 이벤트 버스

### 펜리르 제기 — 17개 침투 시나리오 (P0 4건)
- **1-A CRITICAL**: 프롬프트 인젝션 (injection_guard 로그만, 차단 안 함)
- **1-B CRITICAL**: 셸 인젝션 RCE (notify-completion.py `bash -c` 문자열 조립)
- **9-A CRITICAL**: 토큰 소진 공격 ($324 최악, force+phases+race)
- **2-A CRITICAL**: 무한 Claude 세션 생성 루프 (인메모리 중복방지 → 재시작 시 초기화)

---

## 사이클 2+3: 통합 설계 결정 (반론 반영 수정안)

### 아키텍처 결정
- **이름**: `auto_orch.py` (오딘 원안 채택, tick 명명 기각)
- **폴링 간격**: 30초 (오딘 원안. 5초는 CPU 낭비 대비 이득 미미)
- **통합 패턴**: chain.py 무수정 래퍼 + 야누스 독립 상태 디렉토리 통합
- **상태 관리**: JSON 파일 기반 상태 기계 (야누스 기여 채택)
- **Anu 관계**: 독립 피어 유지

### 보안 완화 조치 (전부 채택)
- RISK-01 → TeamLock 클래스 (fcntl.flock LOCK_EX|LOCK_NB)
- RISK-02/06 → gates/ 디렉토리 + .approved 파일 (uid 검증)
- RISK-03 → validate_dag() (Kahn's algorithm)
- RISK-04 → token_ledger.py (DAILY_HARD_LIMIT)
- RISK-05 → outputs 파일 존재 확인 필수
- RISK-07 → allowed_teams 화이트리스트 + blast_radius 선언
- RISK-08 → event_bus.py (원자적 rename 소비)
- RISK-09 → scan_secrets() + env:// 참조 전용
- RISK-10 → rollback_cmd 역순 실행
- 펜리르 1-A → injection_guard 하드블록으로 격상
- 펜리르 1-B → shell=False + shlex.quote() 강제
- 펜리르 9-A → MAX_CONCURRENT_PIPELINES=3 + force 게이트 필요
- 펜리르 2-A → MAX_RETRIES_PER_STEP=2 + 지수 백오프

### 로키 6개 최소 보안 기준 전부 MVP에 포함

---

## 사이클 4: 잔여 불확실성 해소

### 결정 1: DAILY_HARD_LIMIT = 1,000,000 tokens
- Sonnet 기준 최대 15 세션/일 = ~525,000 tokens
- 안전 여유 포함 상한 1M tokens, 비용 ~$18/일 max
- **4인 합의 ✓**

### 결정 2: .approved 파일 uid 검증 = POSIX stat()
- 단일 머신, 동일 사용자(jay) 환경
- SSH 접근 제어 + 디렉토리 권한으로 충분
- JWT 서명은 과도한 복잡도
- **4인 합의 ✓**

### 결정 3: 알림 처리 = shlex.quote() + 항상 발송
- 알림 스킵 금지 (운영 가시성 우선)
- 검증 실패 시 정제된 폴백 메시지 + 로그 기록
- **4인 합의 ✓**

---

## 최종 합의 결과

- **만장일치 합의 달성**: 4차 사이클에서 전원 동의
- **산출물**:
  - 최종 설계서: `memory/specs/automation-agent-spec.md`
  - 보고서: `memory/reports/task-899.1.md`
- **다음 단계**: Phase 1 MVP 구현 (별도 task로 할당 필요)

---

*미팅 기록 종료 — 오딘, 2026-03-24*
