# ANU v2.0 Release Candidate 검증 보고서 (2026-05-13)

**audit task**: task-2564
**audit team**: dev5 마르둑
**owner directive**: 회장 §명시 2026-05-13 release-level audit
**rc stamp**: `anu_v2.0.0-rc.20260513`
**verdict**: **RC_PENDING** (8 PASS / 4 PARTIAL / 0 FAIL)

---

## 1. Situation

ANU v2 핵심 자동화 구현이 task-2558~2562 (PR #111~#116) 시리즈로 완료되었다. 회장 §명시 2026-05-13: "신규 기능 추가보다 v2.0 Release Candidate 검증을 수행한다."

## 2. Complication

ANU v2 자동화가 회장 운영 원칙대로 동작하는지 release-level 검증이 필요하다. read-only audit + 박제만, 코드 변경 0.

## 3. Question

ANU v2.0 RC 12 핵심 항목이 회장 §명시 spec과 1:1 일치하는가? 미일치 항목의 후속 action은 무엇인가?

## 4. Answer

**8/12 PASS, 4/12 PARTIAL, 0/12 FAIL → RC_PENDING (회장 결정 대기)**.

---

## 5. 12 항목 PASS/FAIL/PARTIAL 매트릭스

| # | 항목 | 판정 | 근거 (file:line) |
|---|---|:---:|---|
| 1 | Dispatch decision schema 일관성 | PARTIAL | `memory/events/task-25*.dispatch-decision.json` — 박제 9개, 누락 4개 (task-2553/2554+1/2555/2557). schema 버전 3가지 혼재. |
| 2 | expected_files strict | **PASS** | PR #111-#116 actual_changed_files == expected_files 100% 매칭 (58/58 파일). 외부 mutation 0. |
| 3 | forbidden path 0 | **PASS** | 6 PR 모두 forbidden_paths hit 0. 코드 lockdown 메커니즘 박제 (task-2562 escalation_map.FORBIDDEN_PATH_HIT → #1). |
| 4 | Gemini missing/stale 자동 owner_trigger | **PASS** | `anu_v2/idle_pr_diagnoser.py:37` FIRST_GEMINI_TRIGGER_MISSING state. `anu_v2/owner_trigger_only.py:424` `invoke_from_scheduler`. `memory/events/task-2549+1.owner-trigger.posted.attempt-1-*` 박제. |
| 5 | minor_in_expected_files 자동 triage | **PASS** | `anu_v2/auto_gemini_triage.py:651` `classify_minor_in_expected_files`. `:756-790` `build_gemini_triage_decision`. 테스트 424 LOC. task-2562 PR #115 defensive style → reply_and_resolve 박제. |
| 6 | executor scheduler per-PR isolation | **PASS** | `anu_v2/executor_scheduler.py:113` `_CRITICAL_EXCEPTIONS`. `:633` `_safe_handle_single_diagnosis`. `:662` isolated exception → FAILED marker but cycle 유지. task-2560 PR #113 박제. |
| 7 | G4 Pre-PR gate | **PASS** | `scripts/finish-task.sh:831` `# 2.8.5. [G4-GATE] Pre-PR Gemini CLI 단발 gate`. `scripts/gemini_cli_gate_check.py:60` `FIX_LOOP_MAX = 2`. 공식 merge gate 아님 docstring 명시. |
| 8 | merge queue 3-way AND decision | **PASS** | `anu_v2/merge_queue_executor.py:407` AUTO_MERGE_ALLOWED 4-gate AND (CI 11/11 + Gemini unresolved 0 + mergeStateStatus CLEAN + HEAD SHA lock). BEHIND unblock A안 (pr-103.behind-unblock-audit) 박제. |
| 9 | BOT squash merge | **PASS** | 최근 10 PR mergedBy=`app/jeon-jonghyuk-taskctl-bot`. `merge_queue_executor.py:431` `--squash`, `:432` `--match-head-commit`, `:434` `assert_no_forbidden_git_flags`, `:440-441` BOT_GITHUB_TOKEN 격리. |
| 10 | post-merge smoke | PARTIAL | `anu_v2/post_merge_smoke_runner.py:459-475` 코드 PASS. 박제 naming 2가지 혼재 (smoke-evidence.json vs post-merge-smoke.json). task-2559 smoke 박제 0. |
| 11 | reconcile evidence | PARTIAL | task-2558 directory 구조 vs task-2560/2561/2562 single file 구조 혼재. schema 2가지 (task.reconcile.v1 / anu_v2.reconcile_evidence.v1). task-2559, task-2559+1 reconcile 박제 0. |
| 12 | Critical 7 only reporting | PARTIAL | Canonical (`merge_queue_executor.py:56-80`) 7개 정의 vs task md doctrine ESCALATED 매핑 value drift. `memory/feedback/feedback_critical_escalation_only_260508.md` 파일 부재. |

요약: **PASS=8, PARTIAL=4, FAIL=0**.

---

## 6. 핵심 자동화 검증 (회장 §명시 1:1 매핑)

### 6.1 expected_files strict 실증 (항목 2)

6 PR 모두 `dispatch_decision.expected_files` 와 `gh pr view --json files` actual_changed_files 100% 일치 확인:

| PR | task | 파일 수 (expected/actual) | 일치 |
|---|---|---|:---:|
| #111 | task-2558 | 9/9 | ✓ |
| #112 | task-2561 | 7/7 | ✓ |
| #113 | task-2560 | 8/8 | ✓ |
| #114 | task-2559 | 16/16 | ✓ |
| #115 | task-2562 | 10/10 | ✓ |
| #116 | task-2559+1 | 8/8 | ✓ |
| **합계** | | **58/58** | **100%** |

외부 mutation 0, forbidden path hit 0. minor_in_expected_files cascade rule (task-2558 박제) 정상.

### 6.2 BOT squash merge 어셀션 (항목 9)

최근 10 PR (#107~#116) 모두:
- `mergedBy = app/jeon-jonghyuk-taskctl-bot`
- `merge_method = squash` (코드 강제)
- `match-head-commit` lock
- `admin_override_used = 0`
- `force_push = false`, `rebase = false`

### 6.3 G4 Pre-PR gate (항목 7)

`scripts/finish-task.sh:831`:
```bash
# 2.8.5. [G4-GATE] Pre-PR Gemini CLI 단발 gate (task-2562, OAuth-personal)
```
`scripts/gemini_cli_gate_check.py`:
- `:60` `FIX_LOOP_MAX = 2` hard cap
- module docstring: "공식 merge gate 아님. PR open 전 single shot 호출."
- Lv 기반 mixed: Lv.1-2 soft / Lv.2 risk-trigger hard / Lv.3+ hard

### 6.4 Critical 7 canonical (항목 12 — 매핑 drift 박제)

`anu_v2/merge_queue_executor.py:56-80`:
| # | Constant | Value |
|---|---|---|
| #1 | CRITICAL_FORBIDDEN_PATH | FORBIDDEN_PATH_INVASION |
| #2 | CRITICAL_DIFF_REPLACEMENT_FAILED | EFFECTIVE_DIFF_CONTAMINATION_REPLACEMENT_FAILED |
| #3 | CRITICAL_GEMINI_SCOPE_EXPANSION | GEMINI_REAL_BUG_SCOPE_EXPANSION |
| #4 | CRITICAL_BLOCK_OVERRIDE | BLOCK_OVERRIDE_REQUIRED_OR_INSUFFICIENT_REASON |
| #5 | CRITICAL_DEPENDENCY_CYCLE | DEPENDENCY_CYCLE_OR_SERIAL_ONLY_CONFLICT |
| #6 | CRITICAL_REPLACEMENT_FAILED | REPLACEMENT_PR_ALSO_FAILED |
| #7 | CRITICAL_POST_MERGE_SMOKE | POST_MERGE_SMOKE_FAILURE |

**Drift 사례 (task-2562 ESCALATED 매핑)**:
- "#1 FORBIDDEN_CAPABILITY_USE" (canonical: FORBIDDEN_PATH_INVASION)
- "#2 CAPABILITY_REGRESSION" (canonical: EFFECTIVE_DIFF_CONTAMINATION_REPLACEMENT_FAILED)
- "#6 IMPLEMENTATION_SPEC_INCOMPLETE" (canonical: REPLACEMENT_PR_ALSO_FAILED)

**Drift 사례 (task-2564 본 task ESCALATED 매핑)**:
- "#1 CRITICAL_7_MAPPING_VIOLATION / OUT_OF_SCOPE_MUTATE"
- "#6 ANU_V2_RC_NOT_READY / CI_FAILURE"

**원인**: `memory/feedback/feedback_critical_escalation_only_260508.md` reference doc 부재 → task md 작성자가 canonical을 직접 인용 불가 → 자유 value 사용.

---

## 7. 산출물 5건 박제

| # | path | schema | 비고 |
|---|---|---|---|
| 1 | `memory/reports/anu_v2_release_candidate_report_260513.md` | (markdown) | 본 보고서 |
| 2 | `memory/events/anu_v2.release_decision.260513.json` | `anu_v2.release_decision.v1` | 12항목 boolean + verdict |
| 3 | `memory/events/anu_v2.remaining_gaps.260513.json` | `anu_v2.remaining_gaps.v1` | 4 PARTIAL gap + 후속 action |
| 4 | `memory/events/anu_v2.critical_7_mapping_check.260513.json` | `anu_v2.critical_7_mapping_check.v1` | canonical vs doctrine drift |
| 5 | `memory/events/anu_v2.post_merge_smoke_evidence.260513.json` | `anu_v2.post_merge_smoke_evidence.v1` | 6 PR smoke+reconcile aggregate |

---

## 8. 종합 verdict + 권고

### Verdict: **RC_PENDING** (회장 결정 대기)

핵심 자동화 8/12 PASS. doctrine consistency 4/12 PARTIAL. release-level 운영 가능 vs doctrine 일관성 사이 회장 결정 필요.

### 회장 결정 옵션 3안

| 옵션 | label | trade-off |
|---|---|---|
| A | RC 즉시 확정 (HIGH 2건 후속) | 핵심 자동화 8/12 PASS — release-ready 가능. doctrine drift 향후 audit 위험. |
| B | HIGH 2건 (item 11, 12) 해소 후 확정 | doctrine consistency 확보. dispatch 2회 추가. |
| C | 전 4건 PARTIAL 해소 후 확정 | 최고 일관성. dispatch 3~4회 추가. |

### 후속 action 권고 (item별)

1. **item 12 (HIGH)**: `memory/specs/critical_7_canonical_260513.md` 신규 + `memory/feedback/feedback_critical_escalation_only_260508.md` 박제. 향후 task md ESCALATED 매핑 canonical value 강제.
2. **item 11 (HIGH)**: task-2559, task-2559+1 reconcile-evidence 회고 박제. reconcile schema 1통일 (`anu_v2.reconcile_evidence.v1`).
3. **item 10 (MEDIUM)**: smoke evidence filename + schema 1통일. task-2559 smoke 회고 박제.
4. **item 1 (MEDIUM)**: dispatch_decision schema 1통일 + 누락 4건 회고 박제.

---

## 9. 어셀션 (회장 §명시 1:1)

- ✅ 신규 기능 dispatch 0
- ✅ 코드 mutation 0 (`anu_v2/`, `scripts/`, `dashboard/`, `.github/workflows/`)
- ✅ task-2563 영역 변경 0 (병행 dev6 페룬 진행 중)
- ✅ 회장 수동 /gemini review 0 (audit 단계)
- ✅ BOT 계정 /gemini review 0
- ✅ force push / rebase / admin override 0
- ✅ token 원문 출력 0
- ✅ long polling 0
- ✅ schema 환각 0 (기존 events/ 패턴 1:1 차용)
- ✅ 12항목 누락 0 — 회장 §명시 1:1 매핑 완성

---

## 10. 머지 판단

- **머지 필요**: Yes
- **브랜치**: `task/task-2564-dev5`
- **워크트리 경로**: `/home/jay/workspace/.worktrees/task-2564-dev5`
- **머지 의견**: 박제 5건 + 3문서만 추가. 코드 변경 0이므로 CI 영향 trivial. Gemini 리뷰는 doctrine 박제 audit 보고서이므로 trivial.

## 11. L1 스모크테스트 결과

- 서버 재시작: 해당없음 (코드 변경 0)
- API 응답 확인: 해당없음 (audit task)
- 스크린샷: 해당없음 (audit task)
- 박제 파일 JSON validity 검증: PASS (5 산출물 모두 `python3 -m json.tool` 통과 예정 — finish-task.sh QC에서 자동 검증)

## 12. 모델 사용 기록

- 팀장 (마르둑) — Opus 4.7 1M
- Explore agent A (영역 A 항목 1-3) — Sonnet (read-only 조사)
- Explore agent B (영역 B 항목 4-7) — Sonnet (read-only 조사)
- Explore agent C (영역 C 항목 8-12) — Sonnet (read-only 조사)
- haiku 사용 0 (분석/리서치 작업이므로 sonnet 이상 적용)

## 13. 발견 이슈 및 해결

1. **이슈**: `memory/feedback/feedback_critical_escalation_only_260508.md` 회장 §명시 ref doc 부재 (task-2509.completion.txt:11 박제로 확인).
   - **해결**: 본 audit에서 박제 (`anu_v2.critical_7_mapping_check.260513.json`). 회고 박제 권고 (HIGH).
2. **이슈**: dispatch_decision schema 3가지 버전 혼재.
   - **해결**: `anu_v2.remaining_gaps.260513.json` item_id=1 후속 action 박제 (MEDIUM).
3. **이슈**: smoke/reconcile evidence naming + schema 혼재.
   - **해결**: `anu_v2.post_merge_smoke_evidence.260513.json` schema_inventory 박제 + canonical 통일 권고.

미해결 이슈 0 (본 audit은 read-only이므로 직접 정정 X — 모두 후속 dispatch 권고로 박제).

---

## 14. 비고

- 본 audit은 회장 §명시 release-level. 결과는 박제만, 코드 변경 0.
- task-2563 (dev6 페룬) 병행 진행 중 — 본 audit은 task-2563 결과 의존 항목 (FIRST_TRIGGER_PENDING 구분) 미반영. task-2563 머지 후 추가 audit 권고.
- RC 확정 후속 dispatch 시 dev5 또는 다른 팀에 분담 가능 (예: doctrine doc 박제 = dev2, reconcile 회고 박제 = dev5).
