# task-2670 — PR Watcher Terminal/Callback Root Cause Packet (보고)

- 작성: dev8 라 (★ 2026-05-25/26)
- chair_authorization_id: `CHAIR-AUTH-PR-WATCHER-TERMINAL-CALLBACK-ROOT-CAUSE-20260525-JJONGS-RCA-001`
- 완료 상태: **`PR_WATCHER_TERMINAL_CALLBACK_ROOT_CAUSE_PACKET_READY`**
- 단일소스 task md sha256: `f2de5dd3df6c3d0cb9c8906da346907cdeb267c859ef553fe810da3f9a692d4f` ✓
- base: origin/main `2752182a` · branch `task/task-2670-dev8` · worktree `.worktrees/task-2670-dev8`

---

## 1. 회장 보고 한 줄

> task-2667 dev7 PR #149 watcher 는 poll #12 (t+22.27min) 시점 **fresh Gemini head match + 3 new unresolved** 를 감지하고도 `CHAIR_REQUIRED` 분기 부재로 `None/continue` 폴백 → 18 polls (36min) 헛돌이 → max_watch 도과 LOOP_BOUNDARY. **회장 verbatim 4 후보 모두 적중 (3 P0 + 1 P1)**.

---

## 2. 보고 8 (회장 verbatim 박제)

### 2.1 root cause classification — **복합**
- P0: classify() 5-enum 의 `CHAIR_REQUIRED` 분기 부재 (#1+#2 합산)
- P0: ANU normal callback registrar 호출 부재 (#3)
- P1: LOOP_BOUNDARY 우선순위 elapsed-only (#4)
- 적중 4/4 = #1 #2 #3 #4 모두 (★ analysis sibling §5)

### 2.2 watcher.py code path 인용
- 결함 line: L82-141 (classify) · L184-244 (main)
- 핵심: L141 `return None, "continue"` fall-through 폭 과대 + L226-244 callback fire 0
- 상세 verbatim 인용은 packet sibling §2.2

### 2.3 terminal_state 분류 표 (poll #12)
- 현재 코드 분류: `None/continue` (5 enum 어디에도 매칭 안 됨)
- spec doctrine 정상 분류: **`CHAIR_REQUIRED`** (BLOCKED + fresh Gemini + new unresolved = admin override 필요)

### 2.4 callback registrar code path
- spec §6 step 4 요구: watcher 가 terminal 시 ANU normal callback 발사
- 현재 코드: 0 (watcher.py 내 `cokacdir`·`--cron`·`callback`·`envelope` 0회)
- callback 도착(`schedule_history/29C74592.log` ok)은 별개 schedule 의 부수효과

### 2.5 fix packet diff preview
- 5 fix (★ preview only · 실제 diff 0): Fix#1 classify 보강 / Fix#2 callback registrar / Fix#3 LOOP_BOUNDARY escalate / Fix#4 non-Critical7 정책 (A/B/C) / Fix#5 enum 명명 통합
- 상세: `memory/specs/pr_watcher_terminal_callback_fix_diff_preview_260525.md`

### 2.6 regression suite 3 +5 케이스
- 핵심 3: RS-2670-A (LOOP_BOUNDARY 잔재) · RS-2670-B (poll #12 결정적) · RS-2670-C (callback registrar)
- 부수 5: B-pos / B-neg / B-edge / C-fail / C-skip
- 상세: `memory/specs/pr_watcher_terminal_callback_regression_suite_260525.md`

### 2.7 forbidden_action_count — **0**
- 즉시 코드 수정 0 · PR 0 · merge 0 · dev bot 재dispatch 0 · live settings.json 0 · dispatch.py 0 · hooks live 0 · Axis runtime/HARNESS_ENFORCED/RUNNING 자동 0 · watcher.py 수정 0 · task-2662~2669 파일 충돌 0 · BOT_GITHUB_TOKEN 호출 0

### 2.8 recommended next action
1. 회장 보고: `PR_WATCHER_TERMINAL_CALLBACK_ROOT_CAUSE_PACKET_READY`
2. fix 적용은 별도 회장 verbatim chair_authorization_id 발급 후 신규 task
3. 신규 task expected_files: `utils/ci_watch_handoff_runner.py`, `utils/ci_watch_handoff_schema.py`, `tests/test_ci_watch_handoff_*.py`, `tests/fixtures/poll_history/*.json`
4. `29C74592` workspace 는 사고 박제 보존용 (★ 수정 0)
5. Fix#4 (non-Critical7 gates 정책 A/B/C) 별도 1:1 회장 verbatim 결정 필요

---

## 3. 산출물 색인 (Track G 전용)

- `memory/specs/pr_watcher_terminal_callback_root_cause_packet_260525.md` (★ 통합)
- `memory/specs/pr_watcher_terminal_callback_root_cause_analysis_260525.md`
- `memory/specs/pr_watcher_terminal_callback_fix_diff_preview_260525.md`
- `memory/specs/pr_watcher_terminal_callback_regression_suite_260525.md`
- `memory/events/task-2670.pr-watcher-terminal-callback-rca-result-260525.json`
- `memory/events/task-2670.done` (finalize 시 발행)
- `memory/reports/task-2670.md` (★ 본 파일)

---

## 4. 안전 박제

- 회장 세션 적용 0
- ANU collector 적용 0
- live cokacdir 실호출: ANU normal callback cron 1회 (finalize 단계 · ANU key `c119085addb0f8b7` · self-key 0 · UTF-8 ≤3900 bytes · envelope only · absolute timestamp now+30s)
- BOT_GITHUB_TOKEN (ghs_) 호출 0 · OWNER PAT 호출 0
- watcher.py 변경 0 · dev7 자기 분석 모순 회피
- task-2662~2669 (dev2/dev1/dev4/dev3/dev5/dev6/dev7) 파일 충돌 0 — 본 task prefix `pr_watcher_terminal_callback_*` 차별화

---

## 5. 끝

성공: **`PR_WATCHER_TERMINAL_CALLBACK_ROOT_CAUSE_PACKET_READY`**

끝
