# task-2633 — merge-ready dry-run executor 구현 (Track B · read-only · merge 실행 0)

- Level: Lv.3 (거버넌스 자동화 · dry-run executor)
- 담당: dev6 페룬
- base: origin/main **c80e875d** (merge-ready classifier 머지 반영분)
- 단일소스 spec: `memory/specs/system_merge_ready_executor_dryrun_spec_260522.md`
  - sha256: 정독 전 sha256sum 검증 필수, 불일치 시 중단·ANU 보고
- 승인 범위: **dry-run executor 구현까지만**. 실 merge executor 활성화 미승인(회장 명시).

## 목표
merge-ready classifier output 을 입력으로 받아 verdict 별 routing artifact 를 생성하는 **dry-run executor** 를 구현한다. 실제 merge/push/PR/cron 발사 0 · GitHub write 0 · branch protection 우회 0 · admin override 자동화 0. `actually_executed=false` 와 `WOULD_*` 접두사로 미실행 표식 강제.

## 필수 구현
1. `utils/merge_ready_dryrun_executor.py` — decoupled pure module
2. `dryrun_route(merge_ready_result, pr_identity) -> routing_artifact` 순수함수
3. verdict → routing 매핑(spec §1):
   - PASS → `auto_merge_candidate.json` (executor_action=`WOULD_MERGE`)
   - HOLD → `remediation_required.json` (executor_action=`WOULD_AUTO_REMEDIATE`)
   - CHAIR_REQUIRED → `hold_for_chair.json` (executor_action=`WOULD_ESCALATE_CHAIR`)
   - UNKNOWN → `hold_for_chair.json` with reason=INSUFFICIENT_EVIDENCE (executor_action=`WOULD_REGATHER`)
4. 3종 artifact schema 구현 (spec §2.1/2.2/2.3 정본):
   - `merge_ready.auto_merge_candidate.v1` · `merge_ready.remediation_required.v1` · `merge_ready.hold_for_chair.v1`
5. 안전 불변식 (spec §3):
   - 모든 artifact 에 `actually_executed: false` 강제
   - 모든 executor_action 에 `WOULD_*` 접두사 강제
   - merge/push/PR/cron 발사/branch-protection/admin-override 호출 0 (코드 경로 부재)
   - artifact 쓰기는 본 task 에서는 schema 만 — 실 디스크 쓰기는 향후 wiring task 에서 별도
6. classifier output 의 모든 verdict 4값(PASS/HOLD/CHAIR_REQUIRED/UNKNOWN) 라우팅 커버
7. 입력 evidence 결핍/형식 오류 방어 (None-guard·_as_int 동형 패턴) — classifier 입력 견고성 doctrine 일치

## 필수 fixture (frozen, live 의존 0)
classifier 의 17 fixture 출력값을 입력으로 사용. 신규 fixture 추가 가능하나 expected_files 내부 한정.
- `pass_routing` — PASS verdict → WOULD_MERGE candidate
- `hold_routing_ci_pending` — HOLD → WOULD_AUTO_REMEDIATE
- `hold_routing_gemini_medium` — HOLD → WOULD_AUTO_REMEDIATE
- `chair_routing_critical7` — CHAIR_REQUIRED → WOULD_ESCALATE_CHAIR
- `chair_routing_credential` — CHAIR_REQUIRED → WOULD_ESCALATE_CHAIR
- `unknown_routing` — UNKNOWN → WOULD_REGATHER (hold_for_chair w/ INSUFFICIENT_EVIDENCE)
- `idempotent_routing` — 동일 입력 2회 → byte-identical 출력
- 기타 routing edge case (executor_action 표식 정합·actually_executed 강제·WOULD_* 접두사)

## 필수 regression
- `tests/regression/test_merge_ready_dryrun_executor.py` — 모든 verdict→routing 매핑 + safety invariants(actually_executed/WOULD_* 강제) + idempotency 단언
- full tests/regression 신규 fail 0
- live workspace 의존 0 · live GitHub/git 의존 0

## expected_files (task-2633 범위)
- `utils/merge_ready_dryrun_executor.py` (신규)
- `tests/regression/test_merge_ready_dryrun_executor.py` (신규)
- `tests/fixtures/merge_ready_dryrun/<name>/{evidence,expected,PROVENANCE}` (신규 routing 시나리오)

## 자동수렴 원칙
- Gemini medium/style + expected_files 내부 + Critical7 0 + credential 0 → 자동수렴
- non-critical HIGH 도 expected_files 내부면 자동수렴, 단 동일 함수 HIGH 반복 시 LOOP_BOUNDARY → 회장 보고
- 회장 보고 트리거: Critical7 / credential expansion / expected_files 밖 수정 / admin override / replacement PR fail / post-merge smoke fail

## 금지 (회장 verbatim)
- 실 merge 실행 금지
- GitHub write 금지(주석/리뷰/PR/머지 호출 0)
- branch protection 우회 금지
- admin override 자동화 금지
- auto-merge executor 활성화 금지 (본 task = dry-run 까지만)
- merge_ready_classifier.py 수정 금지(입력 소비만)
- merge-ready classifier expected_files 와 overlap 금지
- foreign dirty 정리 금지 · replacement_pr_runner 수정 금지 · finish-task.sh 수정 금지

## finalize 프로토콜 (★ BOT App token 부재 — 로컬 한정)
1. base = 최신 origin/main c80e875d clean worktree
2. 구현 + fixture + regression 전부 PASS + full new-fail 0
3. **로컬 commit만** (push/PR/merge 금지). finish-task.sh project_path 없이 로컬 종결
4. ANU normal completion callback — **반드시 독립 ANU key `c119085addb0f8b7`** · collector_role=ANU
5. callback envelope UTF-8 ≤3900 bytes · envelope 만: task_id=task-2633 · 로컬 commit SHA · result_path · report_path · 구현 파일 · fixture 검증 · regression 요약 · sha256
6. executor 시작/종료 ts·로컬 commit SHA 명기

이후 ANU: 봇 로컬 commit fresh main 재적층 → OWNER push → PR open → Gemini 자동수렴 → 회장 보고 → 회장 merge 승인.

## frozen anchor (D-SPEC-EXACTNESS)
- ANCHOR-1: "dry-run executor 는 actually_executed=false 강제 · WOULD_* 접두사 강제 · merge 실행 0 · GitHub write 0"
- ANCHOR-2: "verdict 4값(PASS/HOLD/CHAIR_REQUIRED/UNKNOWN) 라우팅 매핑 전부 커버"
- ANCHOR-3: "auto-merge executor 활성화 미승인 — 본 task = dry-run 까지만"
- ANCHOR-4: "merge_ready_classifier 수정 금지 — 입력 소비만"
