---
task_id: task-2511
type: context
scope: task
created: 2026-05-09
updated: 2026-05-09
status: completed
---

# 맥락 노트: task-2511

**task**: task-2511 — auto_gemini_triage

---

## 결정 근거

### [핵심 결정 1] 7-state TriageVerdict 내부 정의 (automation_contracts와 별도)
- task-2509+2 freeze된 `GeminiTriageResult`는 PR-수준 집계.
- task-2511 회장 명시 7-state classifier는 thread-수준 → inner `TriageVerdict` Enum + `ThreadTriageOutcome` dataclass로 분리.
- PR-수준 집계 시 `GeminiTriageResult` (freeze) + `ReviewGateStatus` (freeze)로 변환.
- 추가 보조 dataclass `TriageReport`로 task spec의 `auto_resolved_count` / `blocking_thread_count` / `merge_readiness` 노출.

### [핵심 결정 2] resolveReviewThread payload는 subprocess args 빌더로 분리
- `build_resolve_thread_args(thread_id) -> list[str]` 으로 분리 → dry-run 회귀에서 args 검증 가능.
- `--apply` 모드에서만 subprocess.run 실행 (retry 1회, timeout=30s).
- **G1 권고 반영**: apply 실패 시 `auto_resolved=False`로 명시 (허위 성공 방지).

### [핵심 결정 3] classify_thread 우선순위 (G1 권고 후 재배치)
G1 게이트 권고 반영하여 분류 우선순위 재배치:
1. OUTDATED (isOutdated=True)
2. forbidden path 매칭 (보안 — 항상 최우선)
3. FALSE_POSITIVE (regex/wrapper 패턴 또는 hardcoded path 코멘트)
4. STYLE_ONLY (style hint + bug 단어 부재)
5. CODE_ALREADY_FIXED (commit body/files 매칭)
6. expected_files 차집합 → SCOPE_EXPANSION (false-positive/style 검사 후)
7. MINOR_FIX_ALLOWED (expected_files 안 + minor 패턴)
8. default REAL_BUG_IN_SCOPE

이 순서는 benign 코멘트 ("grep false-positive in docs/x.md")가 path 단순 언급만으로 critical로 escalate되는 사고를 방지한다 (test_19로 검증).

### [핵심 결정 4] review_gate_passed 의미 분리 (G1 권고 후)
- `merge_readiness = (blocking_thread_count == 0)` — 머지 가능 여부 (blocking 기준)
- `review_gate_passed = (blocking_count == 0 AND unresolved_count == 0)` — 후속 wiring 차단 신호
- REAL_BUG_IN_SCOPE 잔여가 있으면 review_gate_passed=False로 wiring(task-2514)이 머지하지 않도록 차단 (test_18 검증).

### [핵심 결정 5] _fetch_pr_threads 실패 시 보수적 처리 (G1 권고 후)
- 빈 결과 fallback이 아니라 RuntimeError raise.
- main()에서 fetch_failed=True 기록 + exit 1로 보수적 신호 (CLEAN 오판 방지).
- owner/repo는 `gh repo view --json owner,name`으로 동적 추출.

## 3 Step Why 결과 (검증 완료)

- **1st Why** (A): review thread state machine 자동화로 PR #61류 stuck 사고를 사람 개입 없이 해소. CI/자동 머지 10조건의 마지막 capability gap.
- **2nd Why** (B): 정책 md 대신 실행 가능 Python 코드 + freeze contracts 사용이 task-2514 wiring 시 plug-in 가능 + 회장 "정책 md만 작성 금지" 부합.
- **3rd Why** (C): 별도 module 분리가 대안(merge_queue_executor inline / 정책 md only)보다 우월. `merge_queue_executor 대규모 수정 금지` 회피 + serial_only policy 부합.
- 일관성: A-B-C 모두 "회장 명시 + freeze contracts 호환 + 후속 wiring 단일 인터페이스"로 일관 — 설계 PASS.

## Codex 게이트 이력

- **1차** (코드 미작성 시): critical FAIL — "산출물 없음" 자명한 지적.
- **2차** (코드 작성 후): critical FAIL — `_fetch_pr_threads` 빈 fallback / apply 허위 성공 / review_gate_passed 잔여 무시 / hardcoded pattern 미통합.
- **3차** (G1 권고 반영 후): **PASS** (critical 0건). 남은 risks 4건은 hardening 권고:
  1. dismiss comment 게시 (향후 task-2514 또는 별도)
  2. GraphQL errors 필드 명시 검사 + post-resolve refresh (향후)
  3. CODE_ALREADY_FIXED diff 기반 강화 (commit files 수집 — 향후 GraphQL query 보강)
  4. architecture expansion / dependency cycle / serial_only collision 분류 (Critical 4종 중 2종 미구현 — 본 task에서는 path 기반 + forbidden path만, 나머지는 향후)

## 참조 자료

- task 명세: `memory/tasks/task-2511.md`
- 정책 본체: `memory/feedback/feedback_critical_escalation_only_260508.md`
- 공통 계약: `utils/automation_contracts.py` (12 dataclass/enum freeze)
- 선행 task: `utils/merge_queue_executor.py`
- 실전 fixture: PR #55 / #56 / #57 / #61
- Codex 결과: `memory/events/task-2511.codex-gate` (PASS 기록)

## 주의사항

- ★ effective diff = 정확히 2 파일 (utils/auto_gemini_triage.py + tests/regression/test_auto_gemini_triage_2511.py).
- ★ `merge_queue_executor.py` / `dispatch.py` / `replacement_pr_runner.py` 미수정.
- ★ `--apply` opt-in (default OFF). dry-run이 default.
- ★ replay fixture 4종 모두 100% offline (gh api / network 호출 없음).
- ★ 향후 hardening (Codex risks 4건)은 task-2514 wiring 또는 별도 task에서 처리.
