# CI_WATCH_HANDOFF 정책 spec (★★★ 새 거버넌스 원칙) — 260523

회장 결정 (2026-05-23 19:38 KST, PR #144 task-2641 OWNER_GEMINI_TRIGGER_ROUTER merge 직전): **ANU 는 CI/Gemini 를 직접 기다리지 않는다. PR open 이후 대기/감시/자동수렴은 반드시 bot 또는 watcher task 에 위임한다.**

배경: ANU 세션-bound background polling 한계 (`ci_watcher_session_lifetime_gap_backlog_260523.json` 박제). 세션 종료 시 polling 도 함께 죽음. PR #143 task-2640 (15분 지연) + PR #144 task-2641 (재반복) 사고.

---

## 1. 새 원칙 (verbatim)

**ANU 는 CI/Gemini 를 직접 기다리지 않는다. PR open 이후 대기/감시/자동수렴은 반드시 bot 또는 watcher task 에 위임한다.**

---

## 2. 역할 분리 (회장 verbatim)

### 2.1 ANU
- batch plan 작성
- dev bot dispatch
- callback 수신
- independent verification
- merge-ready 판정
- Critical7 / 권한 / scope 예외 보고
- consolidated report

### 2.2 dev bot 또는 watcher bot
- PR open 이후 CI 상태 polling
- Gemini review freshness 확인
- OWNER nudge router 실행
- Gemini medium/style/quality 자동수렴
- regression 재실행
- push/thread resolve
- CI/Gemini/phase3 GREEN 확인
- merge-ready 상태가 되면 ANU normal callback 발사

---

## 3. 금지 (회장 verbatim 4 항목)

- ANU 가 직접 "CI 완료 대기 백그라운드 진입" 이라고 보고하는 것 금지
- ANU 가 세션-bound background task 만 믿고 자동수렴을 약속하는 것 금지
- 회장 입력을 기다리는 방식으로 CI watcher 를 운영하는 것 금지
- 회장에게 "나중에 확인해달라" 를 기본 경로로 요구하는 것 금지

---

## 4. CI_WATCH_HANDOFF 필수 필드 (회장 verbatim)

| field | 설명 |
|---|---|
| `pr_number` | int. 대상 PR 번호 |
| `head_sha` | str. 40-char hex. watcher 가 stale 판정 기준점 |
| `branch` | str. branch 이름 |
| `expected_files` | list[str]. 자동수렴 허용 scope |
| `forbidden_paths` | list[str]. 수정 시 즉시 CHAIR_REQUIRED |
| `watcher_owner` | str. dev bot name 또는 "cron-watcher" |
| `max_watch_minutes` | int. hard timeout. default=120 |
| `poll_interval_seconds` | int. CI polling 간격. default=60 |
| `gemini_nudge_policy` | dict. OWNER_GEMINI_TRIGGER_ROUTER 호출 조건 + 1회 hard limit |
| `auto_remediation_policy` | dict. expected_files 내부 medium/style/quality/non-critical HIGH 자동수정 허용 |
| `callback_on_terminal_state` | bool. terminal 도달 시 ANU normal callback 발사 (default=true) |
| `terminal_states` | list[str]. enum (아래 §5) |

---

## 5. terminal_states (회장 verbatim 5 enum)

- `MERGE_READY` — CI 11/11 + Gemini fresh + 0 unresolved + CLEAN + mergeable
- `CHAIR_REQUIRED` — Critical7 / credential expansion / expected_files 밖 수정 / admin override 필요 / post-merge smoke fail
- `GEMINI_EXTERNAL_TRIGGER_STALE` — OWNER nudge 1회 hard limit 후에도 fresh review 미도착
- `CI_FAILED_NON_REMEDIABLE` — 자동수렴 불가능한 CI failure (test regression / forbidden path 등)
- `LOOP_BOUNDARY` — 동일 함수 HIGH 반복 + 자동수렴 무한 루프 방지

---

## 6. Watcher 방식 (회장 verbatim 5 단계)

1. **PR 을 연 주체가 dev bot 이면 dev bot 이 계속 watcher 역할을 맡는다.**
2. **ANU 가 OWNER 권한으로 PR 을 연 경우, 즉시 별도 watcher cron 또는 dev bot watcher 를 발사한다.**
3. **watcher 는 CI/Gemini 가 terminal state 에 도달할 때까지 polling 한다.**
4. **watcher 는 terminal state 에서 ANU normal callback 을 발사한다.**
5. **ANU 는 callback 을 받은 뒤에만 consolidated report 를 낸다.**

---

## 7. Gemini 처리 (회장 verbatim)

- Gemini fresh evidence 가 없으면 watcher 가 `OWNER_GEMINI_TRIGGER_ROUTER` 를 사용한다 (PR #144 OWNER_GEMINI_TRIGGER_ROUTER stack 활용)
- 회장 UI 입력은 **최후수단**
- OWNER nudge 실패/권한 오류 시에만 회장 보고

---

## 8. 자동수렴 정책 (회장 verbatim)

- **watcher 가 자동수렴**: expected_files 내부 Gemini medium/style/quality/non-critical HIGH
- **ANU callback 으로 회장 보고**: Critical7 / credential/permission expansion / expected_files 밖 수정 / admin override 필요 / post-merge smoke failure

---

## 9. ANU 완료 보고 8 항목 (회장 verbatim)

1. CI_WATCH_HANDOFF 생성 여부
2. watcher 주체
3. watcher schedule_id 또는 bot session id
4. terminal state
5. 자동수렴 내역
6. CI/Gemini/phase3 최종 상태
7. merge-ready 여부
8. ANU callback 수신 여부

---

## 10. 즉시 후속 task (회장 verbatim)

**CI_WATCH_HANDOFF_RUNNER task 발행** — ANU 가 직접 대기하지 않고, PR open 이후 watcher bot/cron 이 terminal state 까지 책임지게 하는 것.

### 10.1 후속 task 범위 (예상)
- 신규 모듈: `utils/ci_watch_handoff_runner.py` (CI/Gemini polling + auto-remediation + callback 발사)
- 신규 helper: `utils/ci_watch_handoff_schema.py` (CI_WATCH_HANDOFF JSON v1 schema)
- OWNER_GEMINI_TRIGGER_ROUTER (PR #144) 통합 — fresh evidence 미도착 시 1차 OWNER nudge
- terminal state 분류 + ANU normal callback 발사 (envelope ≤3900 bytes)
- fixture / regression / Track A 본체 + 본 spec read-only

회장 명시 결정 시 task ID 발행 + dispatch.

---

## 11. 안전 불변식

- ANU key `c119085addb0f8b7` 단일 출처 유지
- OWNER_GEMINI_TRIGGER_TOKEN 단일 출처 (BOT_GITHUB_TOKEN 사용 0)
- envelope UTF-8 ≤3900 bytes 유지
- callback prompt ≤2800 권장
- live cokacdir / gh CLI 실호출은 watcher 만 (ANU 직접 0)
- merge/push/PR/admin override = ANU 직접 0 (필요 시 watcher 위임)
- real auto-merge activation 0
- forbidden 15종 + 기존 owner_trigger 4종 무수정

---

## 12. frozen anchor

- ANCHOR-1: "ANU 는 CI/Gemini 를 직접 기다리지 않는다 — PR open 이후 watcher 위임"
- ANCHOR-2: "회장 verbatim 4 금지 (CI 완료 대기 백그라운드 약속 / session-bound 자동수렴 약속 / 회장 입력 기다리는 CI watcher / 나중에 확인해달라 기본 경로)"
- ANCHOR-3: "CI_WATCH_HANDOFF 12 필수 필드 (pr/head/branch/expected_files/forbidden_paths/watcher_owner/max_watch_minutes/poll_interval/gemini_nudge_policy/auto_remediation_policy/callback_on_terminal_state/terminal_states)"
- ANCHOR-4: "terminal_states 5 enum (MERGE_READY/CHAIR_REQUIRED/GEMINI_EXTERNAL_TRIGGER_STALE/CI_FAILED_NON_REMEDIABLE/LOOP_BOUNDARY)"
- ANCHOR-5: "Watcher 5 단계 (dev bot 연 PR = dev bot watcher / ANU 연 PR = 별도 watcher 즉시 발사 / terminal 까지 polling / callback 발사 / ANU 는 callback 후에만 consolidated report)"
- ANCHOR-6: "Gemini fresh 없으면 watcher → OWNER_GEMINI_TRIGGER_ROUTER 1차 / 회장 UI 최후수단 / OWNER nudge 실패 시 회장 보고"
- ANCHOR-7: "자동수렴 = watcher 책임 (expected_files 내부 medium/style/quality/non-critical HIGH) / ANU callback 보고 = Critical7+credential+expected_files 밖+admin override+post-merge smoke fail"
- ANCHOR-8: "ANU 8 완료 보고 항목 (handoff 생성/watcher 주체/schedule_id/terminal_state/자동수렴/CI 상태/merge-ready/callback 수신)"
- ANCHOR-9: "즉시 후속 = CI_WATCH_HANDOFF_RUNNER task · watcher bot/cron 이 terminal까지 책임"
- ANCHOR-10: "CLAUDE.md + MEMORY.md + anu-guide.md 3 파일 박제 강제 (회장 verbatim 마지막 결정)"
