# 자동화 오케스트레이터 통합 구현 계획서
> 버전: 1.0 | 작성일: 2026-03-24 | 작성자: 오딘 (2팀장) | 에이전트 미팅 만장일치 합의
> 기반: task-897.1 (done-polling-spec), task-899.1 (automation-agent-spec)

---

## 1. 전체 아키텍처 레이어 구조

```
Layer 3: auto_orch.py (파이프라인 오케스트레이션) — 30초 systemd timer
Layer 2: .done 감지 (notify-completion + done-watcher) — 이벤트 감지/알림
Layer 1: 기존 시스템 (dispatch.py + chain.py + chain_manager.py) — 작업 위임/체이닝
Layer 0: cokacdir + Telegram — 통신 인프라
```

---

## 2. Phase 로드맵

### Phase 1: .done 감지 인프라 (Layer 2) — 팀 배정: dev1-team

**목표**: 토큰 0 즉시 알림 + 기존 버그 수정

**산출물**:
1. `scripts/notify-completion.py` — `send_telegram_notification()`: `cokacdir --cron` → `requests.post()` 직접 Telegram API 교체
1b. `scripts/activity-watcher.py` — `send_telegram_notification()`: 동일 교체 (cokacdir 사용 0건 목표)
2. `scripts/activity-watcher.py` — `find_done_file` 팀 기반 매칭 수정 (`get_active_task_for_team()` 구현 포함) + `BOT_TEAM_MAP` dev4-8 추가 + `check_already_notified()` → `.done.notified` 마커 기반으로 교체
3. `~/.config/systemd/user/activity-watcher.service` — systemd user service 신규 (Restart=on-failure, StartLimitIntervalSec=60s, StartLimitBurst=3)
4. `scripts/done-watcher.sh` — 미알림 .done 감지 + flock + O_EXCL + 배치 알림 + task_id Python 인라인 삽입 금지 (환경변수 방식)

**검증 기준**:
- T1: 단일 팀 완료 → Telegram 1건 수신 (즉시)
- T3: Layer 1 실패 → Layer 2 fallback 30초 이내
- T6: symlink .done → 처리 거부
- notify-completion.py pyright 0 에러
- activity-watcher.py pyright 0 에러

**의존성**: 없음 (독립 실행 가능)
**예상 규모**: ~150 LOC 변경

---

### Phase 2: 보안 기반 (Layer 3 전제 조건) — 팀 배정: dev2-team (보안팀 리뷰)

**목표**: auto_orch.py 동작 전 필수 보안 인프라 확보

**산출물**:
1. `utils/injection_guard.py` 패치 — 하드블록 격상 (로그만 → 차단)
2. `orchestrator/pipeline_validator.py` — YAML 스키마 검증 + DAG 검증 + 시크릿 스캔 (~80 LOC)
3. `orchestrator/token_ledger.py` — 일일 토큰 한도 + 파이프라인별 예산 (~60 LOC)
4. `orchestrator/event_bus.py` — 원자적 .done 이벤트 소비 (~50 LOC)

**검증 기준**:
- pipeline_validator: 순환 DAG 감지, 시크릿 패턴 차단, 필수 필드 검증
- injection_guard: 인젝션 패턴 하드블록 작동
- token_ledger: DAILY_HARD_LIMIT 초과 시 거부
- event_bus: TOCTOU 경합 테스트 (2개 프로세스 동시 소비 → 1개만 성공)
- pyright 0 에러, pytest 전건 통과

**의존성**: Phase 1 완료 불필요 (독립 실행 가능, 단 Phase 1과 병렬 실행 권장)
**예상 규모**: ~250 LOC 신규

---

### Phase 3: 오케스트레이터 코어 (Layer 3 MVP) — 팀 배정: dev2-team

**목표**: auto_orch.py 메인 로직 구현

**산출물**:
1. `orchestrator/auto_orch.py` — 메인 오케스트레이터 (~300 LOC)
   - `--scan`: 트리거 스캔 + 진행 중 파이프라인 관리
   - `--run <id>`: 수동 파이프라인 시작
   - `--status`: 실행 중 파이프라인 조회
   - `--list`: 등록된 파이프라인 목록
   - `--validate <f>`: YAML 검증만
2. `orchestrator/locks/` — TeamLock (fcntl.flock 기반 팀별 뮤텍스)
3. `orchestrator/state/` — 파이프라인 실행 상태 JSON
4. `~/.config/systemd/user/auto-orch.timer` — 30초 systemd timer
   필수 필드: OnUnitActiveSec=30s, AccuracySec=1s, Persistent=false
5. `~/.config/systemd/user/auto-orch.service` — oneshot service
   필수 필드: Type=oneshot, TimeoutStartSec=25s, MemoryMax=512M, KillMode=process, EnvironmentFile=/home/jay/workspace/.env.keys
6. `auto_orch.py` 시작 시 `/tmp/auto-orch.lock`에 `fcntl.flock(LOCK_EX|LOCK_NB)` 전역 락 (systemd 레벨 동시 실행 방지)

**검증 기준**:
- `--scan` dry-run: 트리거 평가 로직 단위 테스트
- TeamLock: 동시 접근 시 후발 프로세스 거부
- chain.py + dispatch.py subprocess 호출 (shell=False)
- 상태 파일 정합성 (crash 후 재시작 → 상태 복구)
- pyright 0 에러, pytest 전건 통과

**의존성**: Phase 2 완료 필수 (pipeline_validator, token_ledger, event_bus 필요)
**예상 규모**: ~350 LOC 신규

---

### Phase 4: Layer 2↔3 통합 + 이벤트 흐름 정비 — 팀 배정: dev1-team + dev2-team 합동

**목표**: .done 이벤트 흐름에서 Layer 2(알림)와 Layer 3(오케스트레이션) 충돌 방지

**핵심 설계 — .done 이벤트 소비 분리**:
```
.done 파일 생성 (finish-task.sh)
  ↓
[Layer 2 - 알림 경로] notify-completion.py
  → .done.notified 마커 생성
  → Telegram 알림 발송
  → 체인 인식: chain_manager.py next 호출 (기존 체이닝)
  ※ .done 파일 자체를 소비(삭제/이동)하지 않음

[Layer 3 - 오케스트레이션 경로] event_bus.py
  → orchestrator/incoming/ 디렉토리에 이벤트 복사
  → 원자적 rename으로 단일 소비 보장
  → auto_orch.py가 파이프라인 트리거 평가
  ※ 원본 .done 파일은 보존 (Layer 2와 독립)
```

**산출물**:
1. `event_bus.py` 수정 — `memory/events/*.done` 스캔 → `orchestrator/incoming/` 복사 + rename 소비
2. `notify-completion.py` 확인 — .done 원본 미삭제 보장 (현재도 미삭제이므로 변경 없음 예상)
3. 통합 테스트 스크립트 — T1-T8 (task-897.1 시나리오) + 파이프라인 E2E 테스트

**검증 기준**:
- Layer 2 알림 + Layer 3 오케스트레이션이 동일 .done에 대해 독립 작동
- 중복 알림 0건, 중복 파이프라인 시작 0건
- 16팀 동시 완료 시 알림 + 오케스트레이션 정상 동작
- 아누 수동 체이닝(chain_manager.py)과 auto_orch 자동 체이닝 공존 확인

**의존성**: Phase 1 + Phase 3 완료 필수
**예상 규모**: ~100 LOC 수정/신규

---

### Phase 5: 토큰 회계 통합 + 모니터링 — 팀 배정: dev2-team

**목표**: task-timer.py ↔ token_ledger.py 데이터 연동, 운영 가시성 확보

**산출물**:
1. `token_ledger.py` 확장 — task-timers.json에서 Sonnet/Opus 세션 수 추정 → 토큰 소비 추적
2. `orchestrator/health.json` — 매 tick 갱신 (활성 파이프라인, 토큰 사용량, 오류 수)
3. Telegram 경고 통합 — 토큰 80% 도달, 스텝 타임아웃, 파이프라인 실패
4. `auto_orch.py` 확장 — `--status` 결과에 토큰 사용량 포함

**검증 기준**:
- DAILY_HARD_LIMIT 80% 도달 시 Telegram 경고 발송
- health.json 매 tick 갱신 확인
- task-timers.json 데이터와 token_ledger.json 정합성

**의존성**: Phase 3 완료 필수
**예상 규모**: ~120 LOC 수정/신규

---

### Phase 6: 파이프라인 YAML + 유스케이스 — 팀 배정: 해당 팀 (마케팅, 콘텐츠 등)

**목표**: 실제 파이프라인 YAML 작성 + 첫 파이프라인 dry-run

**산출물**:
1. `pipelines/marketing-dev-pipeline.yaml` — GA4 설계 → Dev 구현 → QC 검증
2. `pipelines/templates/` — 각 스텝별 task_file 템플릿
3. `pipelines/content-pipeline.yaml` — 콘텐츠 파이프라인 (수동 트리거)
4. dry-run 로그

**검증 기준**:
- pipeline_validator 전건 통과
- `auto_orch.py --validate` 성공
- dry-run 모드로 전체 흐름 시뮬레이션

**의존성**: Phase 3 + Phase 4 완료 필수
**예상 규모**: YAML + 템플릿 문서 작업

---

## 3. 의존성 그래프

```
Phase 1 ──────────────────────────┐
(Layer 2 .done 인프라)            │
                                   ├──→ Phase 4 ──→ Phase 6
Phase 2 ──→ Phase 3 ──────────────┘    (통합)      (파이프라인)
(보안 기반)   (auto_orch MVP)     │
                                   └──→ Phase 5
                                        (토큰/모니터링)
```

- Phase 1 ↔ Phase 2: **병렬 실행 가능** (상호 의존 없음)
- Phase 3: Phase 2 완료 필수 (보안 컴포넌트 의존)
- Phase 4: Phase 1 + Phase 3 완료 필수 (양 레이어 통합)
- Phase 5: Phase 3 완료 필수 (auto_orch 기반)
- Phase 6: Phase 4 완료 필수 (통합 흐름 확인 후)

---

## 4. 팀 배정안

| Phase | 주 담당 | 보조/리뷰 | 사유 |
|-------|---------|-----------|------|
| Phase 1 | dev1-team (헤르메스) | 로키(보안 리뷰) | task-897.1 설계자, .done 감지 도메인 전문성 |
| Phase 2 | dev2-team (오딘) | 로키+펜리르(보안 승인) | 보안 인프라, 로키 6대 기준 직접 검증 |
| Phase 3 | dev2-team (오딘) | 야누스(systemd 설정) | auto_orch 핵심 로직, task-899.1 설계 기반 |
| Phase 4 | dev1+dev2 합동 | 로키(충돌 검증) | Layer 2(dev1) + Layer 3(dev2) 통합 |
| Phase 5 | dev2-team (오딘) | — | auto_orch 확장 |
| Phase 6 | 해당 유스케이스 팀 | dev2-team(검증) | 실제 사용팀이 YAML 작성 |

---

## 5. 전체 일정 추정 (참고용)

| Phase | 예상 규모 | 비고 |
|-------|-----------|------|
| Phase 1 | ~150 LOC | 기존 코드 수정 위주 |
| Phase 2 | ~250 LOC | 신규 모듈 4개 |
| Phase 3 | ~350 LOC | 핵심 로직 |
| Phase 4 | ~100 LOC | 통합 + 테스트 |
| Phase 5 | ~120 LOC | 확장 |
| Phase 6 | YAML/문서 | 팀별 작성 |
| **총계** | **~970 LOC** | |

---

## 6. 리스크 및 완화

| 리스크 | 심각도 | 완화 방안 |
|--------|--------|-----------|
| Layer 2↔3 .done 소비 경쟁 | Critical | event_bus.py가 복사 후 소비, 원본 보존 + Layer 2 rename 시 event_bus 재처리 메커니즘 (Phase 4 확정) |
| Anu-auto_orch 동시 dispatch | Critical | TeamLock (fcntl.flock LOCK_NB) |
| 파이프라인 무한루프 | High | validate_dag() + MAX_RETRIES=2 |
| 토큰 폭주 | High | DAILY_HARD_LIMIT + MAX_CONCURRENT=3 |
| done-watcher.sh bash→python 인젝션 | Critical | task_id를 환경변수로 전달, Python 인라인 직접 삽입 금지 |
| inject_context source path traversal | High | pipeline_validator에서 source 경로 WORKSPACE_ROOT 하위 검증 |
| systemd 레벨 동시 실행 | High | auto_orch.py 전역 flock + Type=oneshot + Persistent=false |
| Phase 1↔2 병렬 충돌 | Low | 독립 파일/디렉토리, 충돌 없음 |

---

*계획서 초안 종료 — 에이전트 미팅 검토 대기*
