# GEMINI_SECOND_REVIEW_BOTTLENECK 자동화

**프로젝트**: gemini-second-review-bottleneck_260513
**작성일**: 2026-05-13
**작업 레벨**: Lv.4 시스템 아키텍처
**담당**: dev2-team (오딘) 단일팀 한정승인
**task ID**: task-2565
**Phase 진행**: 4 Phase 일괄 위임, 각 Phase phase-gate marker로 끊어 진행
**구현 형태**: 코드/파일 자동화 (정책 문서 X)
**status**: in-progress (Phase 1-3 완료, Phase 4 머지 단계 진행 중) — 2026-05-13

---

## 1. 분류 (Classification)

- **GEMINI_SECOND_REVIEW_BOTTLENECK** (자동 처리 대상, Critical 7 미포함)
- **FOLLOW_UP_COMMIT_STALE_GEMINI**
- **GEMINI_STALE_ON_HEAD_AFTER_FOLLOW_UP**

부가 분류:
- **STATE_INTEGRITY_BLOCKED** (별도 HOLD, 본 task 범위 밖이지만 dev2가 감지 시 `merge_queue_decision=BLOCKED` 처리)

## 2. 문제 정의

follow-up commit 이후 PR current head가 변경되었으나 Gemini evidence가 old head에만 존재 → CI gate가 SHA mismatch로 실패하는 패턴 반복.

관찰 사례:
- **dev6**: old Gemini SHA `d251399c` → follow-up push `cee55afe` → CI stale fail
- **dev5**: merge-ready 상태에서 report/QC Verdict wording 보강 commit push → 새 head 생성 → Gemini second-review 병목 재발

## 3. 목표

- follow-up commit 후 Gemini fresh re-review 대기 병목을 `ExecutorScheduler` / `owner_trigger_only` / CI rerun / `merge_queue_decision` 레벨에서 자동 처리
- 회장 수동 `/gemini review` 요청 절대 금지
- MERGE_READY 상태 report-only pre-merge commit 차단 + post-merge evidence redirect

## 4. 상태 머신 (9 상태 enum)

1. `FOLLOW_UP_COMMIT_CREATED`
2. `GEMINI_EVIDENCE_STALE_ON_HEAD`
3. `SECOND_REVIEW_PENDING`
4. `SECOND_REVIEW_TRIGGER_REQUIRED`
5. `SECOND_REVIEW_OWNER_TRIGGER_POSTED`
6. `SECOND_REVIEW_FRESH_DETECTED`
7. `SECOND_REVIEW_TIMEOUT`
8. `CI_RERUN_REQUIRED_AFTER_FRESH`
9. `MERGE_READY_AFTER_SECOND_REVIEW`

자동 판정 4조건 (모두 충족 시 `GEMINI_STALE_ON_HEAD_AFTER_FOLLOW_UP`):
1. follow-up commit 후 PR current head 변경됨
2. latest Gemini review `commit_id` ≠ current head SHA
3. CI gate failure reason = evidence stale / SHA mismatch
4. unresolved thread가 old head 기준이거나 OUTDATED 상태

## 5. 정책 상수 (polling_policy.py)

```python
SECOND_REVIEW_GRACE_SECONDS = 180          # follow-up 후 fresh evidence 대기
MAX_SECOND_REVIEW_RECHECKS = 1             # owner_trigger 호출 후 max 1회 재확인
LONG_POLLING_FORBIDDEN = True              # long polling 금지 (상수 assertion)
SECOND_REVIEW_OWNER_TRIGGER_DEDUPE_KEY = "pr_number+head_sha"  # same-head dedupe
```

## 6. Phase 분리 (4 Phase)

### Phase 1 — Schema + Policy 상수
**파일**:
- `anu_v2/second_review_recovery.py` (신규 골격)
- `anu_v2/polling_policy.py` (상수 추가)

**구현**:
1. 9 상태 enum 정의
2. `second_review_decision.v1` schema (12 필드)
3. `pre_merge_commit_decision.v1` schema (6 필드)
4. polling_policy 상수 4개

**Tests**: schema validation / enum serialization / long polling forbidden assertion / grace·recheck default assertion

**Gate marker**: `memory/events/task-2565.phase-1.schema-policy.done`

### Phase 2 — Stale Detection + Owner Trigger 자동 호출
**파일**:
- `anu_v2/second_review_recovery.py` (확장)
- `anu_v2/executor_scheduler.py` (detection hook 호출)

**구현 8단계**:
1. follow-up commit 후 current head vs latest Gemini commit_id 비교
2. mismatch 시 `GEMINI_STALE_ON_HEAD_AFTER_FOLLOW_UP` 분류
3. `SECOND_REVIEW_PENDING` marker 생성
4. 180초 grace 후 `SECOND_REVIEW_TRIGGER_REQUIRED`
5. `owner_trigger_only` runner 자동 호출
6. same-head DEDUPED 확인 (`owner_trigger_audit.jsonl` 조회)
7. 7 marker 파일 생성
8. `owner_trigger_audit.jsonl` append

**7 Marker**:
- `memory/events/task-2565.second-review-decision.json`
- `memory/events/task-2565.gemini-stale-on-head-after-followup`
- `memory/events/task-2565.second-review-owner-trigger-requested`
- `memory/events/task-2565.second-review-owner-trigger-posted`
- `memory/events/task-2565.second-review-fresh-detected`
- `memory/events/task-2565.ci-rerun-after-fresh`
- `memory/events/task-2565.merge-ready-after-second-review`

**Fixture #1 (dev6 case)**: old SHA `d251399c` + follow-up `cee55afe` + CI mismatch → expected: owner_trigger_only auto call

**Tests**:
- `test_follow_up_commit_marks_gemini_stale_on_head`
- `test_second_review_owner_trigger_called_after_grace`
- `test_same_head_duplicate_owner_trigger_deduped`

**Gate marker**: `memory/events/task-2565.phase-2.owner-trigger.done`

### Phase 3 — CI rerun + MERGE_READY pre-merge guard
**파일**:
- `anu_v2/merge_queue_executor.py` (CI rerun + pre-merge guard 추가)
- `anu_v2/second_review_recovery.py` (guard helper 확장)

**구현 — CI rerun 자동 조건**:
1. Gemini fresh evidence exists on current head
2. `gemini-review-gate` 또는 `phase3-merge-gate`가 stale evidence reason으로 실패
3. current head unchanged
4. unresolved thread 0 또는 triage 진행 가능

**수행**: failed CI jobs rerun → rerun marker → CI 11/11 SUCCESS 확인 → `merge_queue_decision` 갱신

**금지** (assertion으로 박제):
- fresh evidence 없이 CI rerun 반복 금지
- same failed job 무한 rerun 금지
- long polling 금지

**구현 — MERGE_READY pre-merge commit 차단**:

merge_ready 5조건:
- CI 11/11 SUCCESS
- Gemini fresh on current head
- unresolved 0
- `mergeStateStatus` CLEAN
- effective diff == expected_files
- forbidden path 0

차단 대상 5종 (report/QC wording/evidence wording-only):
- report wording only
- QC Verdict section wording only
- lifecycle marker wording only
- non-functional summary update
- evidence text 보강

처리 방식:
- merge 전 필수 evidence이면 첫 commit 또는 PR 생성 전 포함
- merge 후 기록해도 되는 내용이면 post-merge smoke / reconcile evidence / lifecycle marker에 기록
- merge-ready 이후 report-only commit 시도 시 `BLOCK_PRE_MERGE_REPORT_ONLY_COMMIT`으로 차단

**Primary mechanism**: push 직전 executor guard / `merge_queue_executor` guard
**Secondary**: pre-commit hook은 optional 또는 dry-run evidence 수준만

**필수 decision**: `memory/events/task-2565.pre-merge-commit-decision.json` (schema `anu_v2.pre_merge_commit_decision.v1`)

**Fixture #2 (dev5 case)**: CI 11/11 + Gemini fresh + CLEAN + report/QC Verdict only commit → expected: `BLOCK_PRE_MERGE_REPORT_ONLY_COMMIT`
**Fixture #3 (race case)**: fresh Gemini after CI stale fail → expected: CI rerun after fresh

**Tests**:
- `test_fresh_evidence_after_ci_failure_reruns_failed_jobs`
- `test_merge_ready_report_only_commit_blocked`
- `test_post_merge_evidence_redirect_allowed`
- `test_stale_ci_merge_forbidden`

**Gate marker**: `memory/events/task-2565.phase-3.ci-rerun-premerge-guard.done`

### Phase 4 — Integration + BOT squash merge
**구현**:
1. expected_files strict
2. forbidden path 0
3. CI/Gemini/CLEAN
4. BOT squash merge
5. post-merge smoke
6. reconcile evidence
7. 완료 조건 12항목 전수 검증

**필수 산출**:
- `second_review_decision.json` / `pre_merge_commit_decision.json`
- `owner_trigger_audit.jsonl` append (capability 사용 시)
- CI rerun evidence
- `merge_queue_decision` update
- post-merge smoke
- reconcile evidence
- `.done` / `.done.acked` / `merge-done`

**완료**: PR merged by `app/jeon-jonghyuk-taskctl-bot` / admin override 0 / force·rebase 0 / 회장 수동 `/gemini review` 0 / post-merge smoke PASS / reconcile PASS

**Gate marker**: `memory/events/task-2565.phase-4.integration-merge.done`

## 7. Phase 실패 처리

각 Phase 실패 시:
1. 다음 Phase 진행 금지
2. failure decision.json 생성
3. Critical 7 분류 수행
4. **Critical 7 또는 owner decision required일 때만** 회장 보고
5. 자동 recover 가능 시 self-resume (operational nudge)

## 8. Critical / Non-Critical 분류

**자동 처리** (Critical 7 미포함):
- follow-up commit 후 Gemini stale on head
- second review missing
- CI stale failure after fresh evidence race
- report-only pre-merge commit 차단

**회장 보고 대상**:
- `owner_trigger_only` POST 실패
- token boundary violation
- fresh review 후 real bug가 expected_files 밖 수정 요구
- forbidden path 요구
- follow-up commit cap 초과
- CI rerun 반복 실패
- post-merge smoke failure
- taskctl/silent_corruption_guard checksum mismatch 상태에서 merge 우회 시도

## 9. 금지 12항목

1. 회장 수동 `/gemini review` 요청 금지
2. BOT 계정 `/gemini review` 금지
3. close/reopen trigger 금지
4. long polling 금지
5. force push / rebase / admin override 금지
6. merge-ready 상태에서 report-only pre-merge commit 금지
7. fresh Gemini evidence 없이 merge 금지
8. stale CI로 merge 금지
9. same-head owner trigger spam 금지
10. token 원문 출력 금지
11. taskctl checksum mismatch 상태에서 direct merge 금지
12. silent_corruption_guard mismatch 말로만 설명하고 merge 금지

## 10. 추가 주의 — STATE_INTEGRITY_BLOCKED

다음은 본 task 범위 밖이지만 dev2가 감지 시 차단해야 함:
- main workspace task scope 밖 변경 49건 stash
- state checksum 문제
- silent_corruption_guard와 taskctl 알고리즘 불일치
- taskctl 우회 후 BOT direct squash merge 언급

처리:
- MERGE_HOLD (미머지)
- POST_MERGE_INTEGRITY_AUDIT_REQUIRED (이미 머지)
- Critical 7 #4 candidate (taskctl block을 formal override 없이 우회 시)

dev2 task에서: checksum mismatch 감지 시 `merge_queue_decision=BLOCKED` 처리.

## 11. 구현 위치

**신규 분리 모듈**: `anu_v2/second_review_recovery.py`
- executor_scheduler와 merge_queue_executor가 호출

**기존 모듈 확장**:
- `anu_v2/polling_policy.py` (상수)
- `anu_v2/executor_scheduler.py` (detection hook)
- `anu_v2/merge_queue_executor.py` (CI rerun + pre-merge guard)
- `anu_v2/owner_trigger_only.py` (기존 runner 재사용, 새 기능 추가 최소화)

**Tests**: `anu_v2/tests/test_gemini_second_review_bottleneck_2565.py`

**Fixtures**: `anu_v2/fixtures/gemini_second_review_bottleneck/`
- `dev6_old_gemini_sha.json` (fixture #1)
- `dev5_merge_ready_report_only.json` (fixture #2)
- `race_fresh_after_ci_fail.json` (fixture #3)

## 12. 완료 조건 12

1. `second_review_decision` schema 생성
2. follow-up commit 후 stale Gemini 자동 감지
3. `owner_trigger_only` 자동 호출 또는 dedupe
4. fresh evidence 도착 후 CI rerun 자동화
5. merge-ready report-only commit 차단
6. regression fixture 3종 추가
7. tests PASS (6 tests + schema validation)
8. expected_files strict
9. forbidden path 0
10. CI/Gemini/CLEAN
11. BOT squash merge
12. post-merge smoke + reconcile evidence

## 13. Doctrine 강제 포함 (task md prompt에 lint 적용)

- 14단계 finalize 명시
- 8항목 봇 직접 행동 명시
- same-PR post-Gemini push doctrine (위반 시 자동 Option A replacement)
- OWNER_TRIGGER_ONLY_CAPABILITY doctrine (13 구현 원칙)
- bot trigger 금지 / chain limit / long polling 금지

## 14. 검증 시나리오

1. **dev6 재현**: old Gemini SHA + follow-up push → owner_trigger 자동 POST → fresh 감지 → CI rerun → BOT squash merge
2. **dev5 재현**: MERGE_READY + report-only push 시도 → `BLOCK_PRE_MERGE_REPORT_ONLY_COMMIT` marker → post-merge evidence redirect
3. **race**: CI stale fail 후 fresh evidence 도착 → 자동 rerun → SUCCESS
