# task-2509+1 — merge_queue_executor review_gate_passed + fallback_review_passed 코드 자동화

- 작업 유형: **자동화 코드 보강 + 회귀 테스트** (정책 문서 X)
- 작업 레벨: **Lv.3**
- 우선순위: **★★**
- Track: **review_gate_fallback / gemini_unavailable / high_risk_hardening**
- parallel_policy: **serial_only**
- 일시: 2026-05-08
- 회장 결정: 2026-05-08 직접 명령 (PR #58 fallback assumption 코드화)

## ⚠️ 본 task의 본질 — 회장 명시

> PR #58에서 드러난 Gemini quota/unavailable 상황을 명시적으로 코드화한다.
> Gemini thread 0건과 Gemini unavailable을 구분하고, review_gate_passed + fallback_review_passed 구조로 자동 머지 조건을 보강한다.
> 산출물 = 실행 가능한 Python 코드 + 회귀 테스트. 문서는 부속.

## dependency (충족)

- ✅ task-2509.merged (PR #58 → main `38334b09`)

## Merge Topology Gate metadata

```yaml
expected_files:
  - "utils/merge_queue_executor.py"  # 보강 (review_gate_passed + Gemini enum + fallback_review_passed)
  - "tests/regression/test_merge_queue_executor_review_gate_2509p1.py"  # 신규 12 케이스

risk_area: "merge_queue / review_gate / fallback_review / gemini_status"

dependency:
  - "task-2509.merged"

parallel_policy: "serial_only"

merge_queue_position: 5

stale_recheck_required: true

cherry_pick_allowed: false
```

## 실전 회귀 fixture (회장 명시)

- PR #58 케이스: Gemini daily quota limit + gemini-review-gate CI SUCCESS + 자동 머지 진행 + smoke PASS
- main HEAD `38334b09`
- AUTO_MERGE_SUCCESS_WITH_REVIEW_FALLBACK_ASSUMPTION (다그다 자율 추론 → 코드화 대상)

본 fixture는 회귀 테스트 #2 (Gemini quota + fallback_review_passed → PASS)의 입력으로 그대로 재현.

## 필수 구현 7건 (회장 §1~7)

### 1. review_gate_passed 판정 도입
- 기존 자동 머지 10조건 #5 "Gemini thread 0 unresolved" → **review_gate_passed**로 교체
- 정의:
  - **a**: Gemini completed + unresolved_threads == 0
  - **b**: Gemini quota/timeout/unavailable + fallback_review_passed

### 2. Gemini 상태 enum 7종 (회장 명시)

```python
GEMINI_COMPLETED            # inline review 완료, unresolved 0
GEMINI_UNRESOLVED            # inline review 완료, unresolved > 0
GEMINI_UNAVAILABLE_QUOTA     # daily quota limit (PR #58 케이스)
GEMINI_TIMEOUT               # polling timeout
GEMINI_STALE                 # PR head 변경 후 재실행 필요
GEMINI_REAL_BUG              # unresolved + real bug 분류
GEMINI_SCOPE_EXPANSION       # expected_files 밖 수정 요구 → Critical #3
```

### 3. fallback_review_passed 조건 구현 (8건 모두 충족 시 true)
- effective diff == expected_files
- forbidden path 0
- CI all SUCCESS
- mergeStateStatus CLEAN
- HEAD SHA lock 일치
- regression/smoke command defined
- dry-run decision PASS
- **risk level별 static fallback check PASS**

### 4. high/core risk fallback 강화
- 변경 파일 중 다음이 1건이라도 포함되면 risk_level=`HIGH_CORE`:
  - `utils/merge_queue_executor.py`
  - `utils/merge_topology_gate.py`
  - `dispatch.py`
  - `teams/shared/verifiers/*`
- HIGH_CORE 시 fallback 조건 강화 (회장 명시):
  - deterministic checks PASS
  - regression PASS
  - dry-run PASS
  - **static risky pattern scan PASS** (force push / admin override / cherry-pick / manual .done 패턴 정적 검사)
  - 가능하면 second verifier (Codex G1) PASS 포함
- Gemini quota만으로 무조건 통과 금지

### 5. non-dry-run smoke 필수화
| dry_run | smoke_command | 결과 |
|---|---|---|
| True | None | WARN/SKIP 허용 |
| True | defined | smoke 실행 |
| False | None | **BLOCK** (자동 머지 거부) |
| False | defined | smoke 실행 + PASS 필수 |

자동 머지 10조건 #10 "post-merge smoke 정의됨"과 정합.

### 6. 후행 PR stale 재검증 강화 (`recheck_following_prs`)
현재 mergeStateStatus 단순 조회 → 아래 추가:
- BEHIND 감지
- conflict 가능성 감지
- effective diff 변동 감지
- expected_files 유지 여부
- forbidden path 발생 여부
- Gemini stale 여부
- CI 재실행 필요 여부

각 항목 → state machine field로 audit JSON에 기록.

### 7. audit 보강
`memory/orchestration-audit/merge-queue.jsonl` + `memory/events/{task_id}.merge-queue.json`에 다음 필드 추가:
- `gemini_status`: enum 7종 중 1
- `fallback_review_used`: bool
- `fallback_review_passed`: bool (used=true 시만 의미)
- `risk_level`: `LOW` / `MEDIUM` / `HIGH_CORE`
- `review_gate_passed`: bool
- `final_decision`: `AUTO_MERGE_ALLOWED` / `BLOCKED_WITH_REASON: <code>` / `CRITICAL_ESCALATION: <enum>`
- `critical_escalation`: bool + Critical 7종 enum 중 해당 (없으면 null)

## 필수 회귀 테스트 12건 (회장 §1~12)

`tests/regression/test_merge_queue_executor_review_gate_2509p1.py`:

1. Gemini COMPLETED + unresolved 0 → review_gate_passed=true
2. Gemini UNAVAILABLE_QUOTA + fallback_review_passed → review_gate_passed=true (★ PR #58 fixture 재현)
3. Gemini UNAVAILABLE_QUOTA + fallback_review_failed → BLOCK
4. Gemini TIMEOUT + fallback_review_passed → PASS
5. Gemini UNRESOLVED + real_bug → BLOCK
6. Gemini SCOPE_EXPANSION → Critical #3 (`GEMINI_REAL_BUG_SCOPE_EXPANSION`)
7. smoke_command=None + dry_run=True → WARN/SKIP
8. smoke_command=None + dry_run=False → BLOCK
9. HIGH_CORE risk file 변경 + Gemini quota → static risky pattern scan + Codex 요구
10. 후행 PR stale 재검증에서 BEHIND 감지
11. 후행 PR effective diff 오염 감지
12. audit JSON에 7 신규 필드(gemini_status / fallback_review_used / fallback_review_passed / risk_level / review_gate_passed / final_decision / critical_escalation) 기록 검증

## CLI 호환성 유지 (회장 명시 task-2509 인터페이스)

`python3 utils/merge_queue_executor.py --pr <N> --dry-run --task-file <path>`
- 출력 JSON에 신규 필드 포함
- 기존 `AUTO_MERGE_ALLOWED` / `BLOCKED_WITH_REASON` 응답 형식 유지
- breaking change 금지

## 금지 행위 (회장 명시 — 절대 준수)

- 정책 문서만 작성하고 종료 금지 (산출물 = 코드 + 회귀 테스트)
- **Gemini quota를 단순히 thread 0건으로 취급 금지** (★ PR #58 자율 추론 재발 방지)
- force push 금지
- rebase 금지
- admin override 금지
- manual .done 금지
- PR #52/#49/#50/#51 수정 금지
- expected_files 외 수정 금지
- task-2509 본체 인터페이스 breaking change 금지

## allowed_resources

```yaml
allowed_resources:
  read_only_paths:
    - "memory/tasks/task-2509*"
    - "memory/events/task-2509*"
    - "memory/reports/task-2509*"
    - "memory/feedback/feedback_critical_escalation_only_260508.md"
    - "memory/feedback/feedback_merge_topology_gate_260508.md"
    - "memory/orchestration-audit/merge-topology-gate.jsonl"
    - "memory/orchestration-audit/merge-queue.jsonl"
    - "utils/merge_topology_gate.py"
    - "memory/task-timers.json"
    - ".env.keys"
  paths:
    - "memory/tasks/task-2509+1*"
    - "memory/reports/task-2509+1*"
    - "memory/events/task-2509+1*"
    - "utils/merge_queue_executor.py"
    - "tests/regression/test_merge_queue_executor_review_gate_2509p1.py"
  forbidden_actions:
    - "Gemini quota를 thread 0건으로 단순 취급"
    - "force push"
    - "rebase"
    - "admin override (gh pr merge --admin)"
    - "manual .done 생성"
    - "required CI bypass"
    - "PR #52/#49/#50/#51 수정"
    - "expected_files 외 수정"
    - "task-2509 본체 breaking change"
    - "정책 문서만 작성하고 종료"
    - "Critical 7종 외 회장 보고"
    - "amendment 무시 / mid-dispatch correction 무시"
```

## 완료 조건 (회장 명시)

1. ✅ 실행 가능한 Python 코드 수정 (utils/merge_queue_executor.py)
2. ✅ 회귀 테스트 12건 PASS
3. ✅ dry-run으로 PR #58 케이스를 `GEMINI_UNAVAILABLE_QUOTA + fallback_review_passed` 로 재현 (회귀 #2)
4. ✅ Critical 7종 외 회장 보고 0건
5. ✅ Merge Topology Gate 자기참조 PASS
6. ✅ CI 11/11 SUCCESS
7. ✅ 회장 §6 공통 금지 위반 0건
8. ✅ amendment 보호 의무 명시 + 적용 evidence

## 시스템 3문서 참조

- 정책 본체: `memory/feedback/feedback_critical_escalation_only_260508.md`
- task-2509 머지 evidence: `memory/events/task-2509.lifecycle-backfill`
- PR #58 fixture: main HEAD `38334b09`, AUTO_MERGE_SUCCESS_WITH_REVIEW_FALLBACK_ASSUMPTION

## 후행 task (5 모듈 본체)

본 task 머지 후:
1. task-2510 — replacement_pr_runner
2. task-2511 — auto_gemini_triage
3. task-2512 — post_merge_smoke_runner
4. task-2513 — critical_escalation_reporter

## goal_assertions (auto-generated)
- `python3 -c "from utils.merge_queue_executor import GEMINI_UNAVAILABLE_QUOTA, RISK_LEVEL_HIGH_CORE, classify_gemini_status, evaluate_fallback_review, static_risky_pattern_scan; assert classify_gemini_status({'status':'unavailable_quota','unresolved':[]}) == GEMINI_UNAVAILABLE_QUOTA"`
- `pytest tests/regression/test_merge_queue_executor_review_gate_2509p1.py -q`
- `pytest tests/regression/test_merge_queue_executor_2509.py -q`
