# task-2634 — dry-run executor shadow validation (Track B-2 · read-only · merge 실행 0)

- Level: Lv.3 (거버넌스 자동화 · shadow validation)
- 담당: dev6 페룬
- base: origin/main **b2932ce0** (PR #136 dry-run executor 머지 반영분)
- 단일소스 spec: `memory/specs/system_dryrun_executor_shadow_validation_spec_260523.md`
  - sha256: `1b1e265c84d78255eb7c1752c861e3c24d43c006677dd7f269ab74450cc88990`
  - 정독 전 sha256sum 검증 필수, 불일치 시 중단·ANU 보고
- 승인 범위: **shadow validation 까지만**. real merge executor wiring 미승인(회장 명시).

## 목표
dry-run executor (`utils/merge_ready_dryrun_executor.py`) 의 routing 정확성을 historical PR 6건 + synthetic 실패/HOLD 시나리오 10건 = **16 fixture** frozen evidence 로 shadow validation. 실제 merge/push/PR/cron 발사 0 · GitHub write 0 · live 의존 0 · `actually_executed=false` 유지.

## 필수 구현 (spec §7 참조)
1. `tests/fixtures/dryrun_shadow/<scenario>/{evidence.json, expected.json, PROVENANCE.md}` × 16 시나리오 (spec §3)
2. `tests/regression/test_dryrun_executor_shadow_validation.py` — 16 fixture 입출력 byte-equal + actually_executed=false + WOULD_* 접두사 + idempotency + 4 verdict 커버 단언
3. (선택) `tests/fixtures/dryrun_shadow/INDEX.md` — 16 시나리오 인덱스
4. **dryrun_route 함수 본체 수정 금지** — 본 task = validation only

## 16 fixture (spec §3 정본)
PASS 6:
- shadow_pass_pr131_l3_classifier
- shadow_pass_pr132_l1l2_credential_passthrough
- shadow_pass_pr133_l4_wiring_mixed_remediation
- shadow_pass_pr134_e2e_production_code_zero
- shadow_pass_pr135_loop_boundary_resolved
- shadow_pass_pr136_dryrun_only

HOLD 4:
- shadow_hold_ci_pending → WOULD_WAIT_RECHECK
- shadow_hold_gemini_evidence_stale → WOULD_OWNER_GEMINI_REVIEW_NUDGE
- shadow_hold_gemini_medium_within_expected → WOULD_AUTO_FIX_REGRESS_PUSH_RESOLVE_RECHECK
- shadow_hold_unresolved_medium_thread → WOULD_RESOLVE_THREAD_RECHECK

CHAIR_REQUIRED 4:
- shadow_chair_blocking_secret
- shadow_chair_admin_override_required
- shadow_chair_replacement_pr_runner_modified
- shadow_chair_loop_boundary_critical_repetition

UNKNOWN 2:
- shadow_unknown_evidence_missing
- shadow_unknown_lifecycle_incident_normal_miss

## 필수 regression
- `tests/regression/test_dryrun_executor_shadow_validation.py` 16/16 PASS
- `tests/regression/test_merge_ready_dryrun_executor.py` 58/58 유지
- `tests/regression/test_merge_ready_classifier.py` 50/50 유지
- full `tests/regression` new fail 0 (3 pre-existing test_stash_origin_audit_compat 무관)
- live workspace 의존 0 · live GitHub/git 의존 0

## historical PR reference (spec §2)
실제 PR evidence frozen (전부 PASS · WOULD_MERGE 단언):
- PR #131 / task-2624 / head 51baef22 / merge 4b3fde25 / 2026-05-22T08:52:52Z
- PR #132 / task-2627 / head 25ddbf4e / merge 94540f67 / 2026-05-22T09:47:42Z (credential 3-tier passthrough)
- PR #133 / task-2629 / head 92b06188 / merge 9ee79286 / 2026-05-22T11:19:24Z (HIGH+medium mixed remediation)
- PR #134 / task-2630 / head 0565114e / merge 24fadbf8 / 2026-05-22T12:40:31Z (production code 0)
- PR #135 / task-2632 / head 270ebfc4 / merge c80e875d / 2026-05-22T14:56:31Z (LOOP_BOUNDARY round-7)
- PR #136 / task-2633 / head 83e88543 / merge b2932ce0 / 2026-05-22T15:48:39Z (dry-run only)

## 안전 불변식 (spec §6)
- 모든 expected artifact `actually_executed=false` 강제
- 모든 expected `executor_action` WOULD_* 접두사 강제
- merge/push/PR/cron/branch-protection/admin-override/GitHub write 호출 0
- live GitHub/git 의존 0 (frozen evidence only)
- replacement_pr_runner.py 수정 0 · finish-task.sh 수정 0
- merge_ready_classifier.py 수정 0 · merge_ready_dryrun_executor.py 수정 0

## expected_files (task-2634 범위 · spec §9)
- `tests/fixtures/dryrun_shadow/<16 scenario>/{evidence.json,expected.json,PROVENANCE.md}` (48 files)
- `tests/regression/test_dryrun_executor_shadow_validation.py` (1 file)
- (선택) `tests/fixtures/dryrun_shadow/INDEX.md` (1 file)
**총 49~50 files. 프로덕션 코드 0 변경.**

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

## 금지 (spec §10 · 회장 verbatim)
- 실제 auto-merge 실행 금지
- real merge executor wiring 금지
- GitHub write 금지 (주석/리뷰/PR/머지 호출 0)
- branch protection 우회 금지
- admin override 자동화 금지
- NL intake 코드 구현 금지
- foreign dirty 정리 금지
- replacement_pr_runner.py 수정 금지
- finish-task.sh 수정 금지
- merge_ready_classifier.py 수정 금지 (입력 소비만)
- merge_ready_dryrun_executor.py 수정 금지 (본 task = shadow validation only)
- expected_files 외부 수정 금지

## finalize 프로토콜 (★ BOT App token 부재 — 로컬 한정 · spec §13)
1. base = 최신 origin/main b2932ce0 clean worktree
2. 16 fixture + regression 전부 PASS + full new-fail 0 + dryrun 58/58 유지 + classifier 50/50 유지
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-2634 · 로컬 commit SHA · result_path · report_path · 16 fixture 검증 요약 · regression 요약 · sha256
6. executor 시작/종료 ts·로컬 commit SHA 명기

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

## frozen anchor (D-SPEC-EXACTNESS · spec §12)
- ANCHOR-1: "shadow validation = read-only · frozen evidence only · 실제 merge/push/PR/cron/admin-override 호출 0 · live GitHub 의존 0"
- ANCHOR-2: "16 fixture (6 PASS + 4 HOLD + 4 CHAIR_REQUIRED + 2 UNKNOWN) 전부 dryrun_route 입출력 byte-equal 단언"
- ANCHOR-3: "actually_executed=false 강제 · WOULD_* 접두사 강제 (100% 단언)"
- ANCHOR-4: "dryrun_route 본체 · merge_ready_classifier · replacement_pr_runner · finish-task.sh 전부 무수정 (fixture+test only)"
- ANCHOR-5: "real merge executor wiring 미승인 — 본 task = shadow validation 까지만"
