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

# 맥락 노트: task-2519 — repository_policy_adapter

**task**: task-2519

---

## 결정 근거

### 핵심 결정 1: 별도 모듈 (utils/repository_policy_adapter.py) 신설
- **이유**: 회장 §명시 "5 모듈 본체 수정 금지", "merge_queue_executor 대규모 rewrite 금지". capability layer를 freeze한 별도 모듈이 SRP/안정성 측면에서 최선.
- **대안 1 (auto_gemini_triage 내 통합)**: triage 책임 비대화 → 기각
- **대안 2 (merge_queue_executor 내 통합)**: 회장 명시 위배 → 기각
- **대안 3 (정책 문서만 작성)**: 회장 §명시 "정책 문서만 작성 금지" → 기각

### 핵심 결정 2: BlockedReason 7종 enum (deterministic 매칭)
- **이유**: 현재 `mergeStateStatus=BLOCKED`만으로는 원인이 5+ 가지 섞여 있어 action 결정 불가. 7종 enum으로 deterministic 분류 → 단일 action mapping.
- **7종 외 reason 합성 시도 금지** — 회장 명시 7종 정확 매칭

### 핵심 결정 3: AUTOMATION_CAPABILITY_GAP은 BlockedReason의 분류 결과가 아니라 path plan의 escalation marker
- **이유**: REQUIRED_APPROVAL / BRANCH_PROTECTION / PERMISSION_ISSUE 분류 시, "이 자동화로는 해소 불가능" 마커로 사용. 회장 직접 머지 fallback 대신 이 분류를 사용 → 보고 경로는 Critical 7종 외이므로 회장 직접 보고 X (별도 ops 채널)
- Critical 7종에 추가 금지 (회장 §명시 "Critical 7종 외 회장 보고 0건")

### 핵심 결정 4: admin override 정적 차단
- **이유**: 회장 §명시 "admin override 항상 금지". 단순 호출 회피가 아니라 코드 레벨 차단 필요 → subprocess args 검사 helper 도입
- 회귀 테스트로 `--admin`이 args에 포함되면 RuntimeError 발생을 검증

### 핵심 결정 5: auto_gemini_triage hook은 인터페이스만 정의 (호출 lazy import)
- **이유**: task-2519 본 task에서는 호출 인터페이스만 정의, 실제 wiring은 task-2520+. circular import 방지를 위해 lazy import (함수 내부에서 import).

## 3 Step Why 자문 (Lv.3+)

### 1st Why: 왜 이 설계가 필요한가?
**A**: PR #61(BLOCKED, 5 unresolved threads), PR #67(BEHIND, 3 unresolved) 사례에서, 자동화는 매번 "회장 직접 머지" fallback으로 빠졌다. capability/reason layer가 표준화되지 않아 admin override 없이 정상 merge path를 deterministic하게 선택할 수 없었다.

### 2nd Why: 왜 A가 최선의 접근인가? (대안과 비교)
**B**: 현재 `mergeStateStatus`만으로는 원인이 다중적이라 action 매핑 불가. 6 probe(capability) + 7 reason(enum) + path 우선순위 → 단일 deterministic 함수로 해결. 대안(매번 GraphQL 동적 조회)은 호출 비용/캐싱 어려움 + 테스트 어려움. 대안(merge_queue 내 통합)은 회장 §명시 위배. **별도 모듈 + freeze contracts**가 SRP/테스트성/안정성에서 최선.

### 3rd Why: 왜 B가 다른 대안보다 나은가?
**C**: 별도 모듈 = 14건 회귀 테스트로 contracts freeze 가능 + auto_gemini_triage hook 인터페이스로만 연결 = 5 모듈 본체 수정 0 + canonical_workspace_resolver READ ONLY 보존 + automation_contracts 변경 0. 대안(triage 내 통합)은 후속 task에서 수정 시마다 회귀 위험. 대안(merge_queue 내 통합)은 회장 §명시 정면 위배. **별도 모듈 + freeze**만이 회장 §명시 11개 금지 행위 모두를 자연스럽게 만족.

→ **A-B-C 일관성**: 회장 §명시 11개 금지 행위 + Critical 7종 외 보고 0건 + admin override 금지를 동시에 만족하는 유일한 설계는 별도 모듈 + freeze contracts.

## 참조 자료

- task-2517 보고서: `/home/jay/workspace/memory/reports/task-2517.md` (canonical_workspace_resolver 패턴 참조)
- task-2511 보고서: `/home/jay/workspace/memory/reports/task-2511.md` (auto_gemini_triage 인터페이스 참조)
- automation_contracts: `/home/jay/workspace/.worktrees/task-2519-dev2/utils/automation_contracts.py` (EscalationPacket, CriticalEscalationType)
- canonical_workspace_resolver: `/home/jay/workspace/.worktrees/task-2519-dev2/utils/canonical_workspace_resolver.py` (frozen dataclass 패턴)

## 주의사항

- **expected_files 외 수정 0건**: 정확히 2 파일만 신규 추가
- **canonical_workspace_resolver READ ONLY**: import만 가능, 수정 금지
- **automation_contracts 변경 0**: import만 가능, EscalationPacket/CriticalEscalationType 사용 OK
- **auto_gemini_triage 호출 lazy import**: 함수 내부에서 import (circular import 방지)
- **admin override 정적 차단**: `gh pr merge --admin` 호출 시 RuntimeError. 정상 호출 경로에서도 args 검사
- **PR #52/#49/#50/#51 수정 금지**: 회귀 테스트는 fixture로 hard-coded mock JSON만 사용
- **dispatch.py 수정 금지**
- **task-2518 영역 침범 금지** (lifecycle은 task-2518 담당)
- **회장 직접 머지를 기본 해법으로 삼지 않음**: REQUIRED_APPROVAL/PERMISSION_ISSUE/BRANCH_PROTECTION → AUTOMATION_CAPABILITY_GAP 분류

## Codex 사전 검증 결과 (G1)

- 실행: 2026-05-09 10:36, source=codex_companion, pass=false (착수 전 산출물 부재 — 정상)
- risks 4건:
  1. critical: utils/repository_policy_adapter.py + 회귀 테스트 부재 → **구현으로 해소**
  2. high: worktree diff 0 → **구현으로 해소**
  3. high: scripts/taskctl.py에 `merge_cmd.append("--admin")` 경로 잔존 → **scope 외** (회장 §명시 "expected_files 외 수정 금지"). **후속 task 권고 항목**으로 보고서 기록
  4. medium: dependency 모듈 위치 → **worktree에서 작업하면 해결** (origin/main에 모두 존재, task-2517/2511/2509+2 머지 완료)
- 결과 파일: `/home/jay/workspace/memory/events/task-2519.codex-gate`

