# task-2637 — real merge executor wiring (코드화 · activation false default · 실제 merge 실행 0)

- Level: Lv.3 (거버넌스 자동화 · real merge executor wiring 코드화)
- 담당: dev6 페룬
- base: origin/main **88a1f2b0** (PR #139 canonical-root hardening 머지 반영분 · CALLBACK_GOVERNANCE_STACK_PRODUCTION_VERIFIED)
- 단일소스 spec: `memory/specs/system_real_merge_executor_wiring_spec_260523.md`
  - sha256: `bcaf654e981a43083af50879164021c918eeac9753cad3b3ad146209a1a62765`
  - 정독 전 sha256sum 검증 필수, 불일치 시 중단·ANU 보고
- 승인 범위: **real merge executor 코드화/비활성 구현까지만**. 실제 auto-merge 활성화 / real merge 실행 미승인(회장 명시).

## 회장 10 결정 verbatim (반영 필수)
1. activation 절차: env var + chair_authorization JSON 둘 다 필요. 둘 중 하나라도 없으면 NO_OP_NO_AUTHORIZATION.
2. signature 방식: **verbatim token** (1차). HMAC 후속 hardening 후보.
3. gate_snapshot TTL: **5분 확정**.
4. post-merge smoke 실패 시 rollback: **자동 rollback 금지**. 보고 only.
5. low-risk pilot target: 미지정. 코드화 후 별도 선정.
6. artifact 위치: **`memory/events/real_merge/<pr>/<head_sha>/`** 확정.
7. batch scope 확대: pilot 1회 성공 후 별도 결정.
8. dryrun→real switch 위치: **신규 `real_merge_hooks` 모듈**. finalize_hooks 직접 확장 최소화.
9. forbidden paths 갱신: 명시 정책 우선. 자동 갱신 후속.
10. 코드화 task 발행: 승인.

## 목표
spec §1~§14 설계를 코드화. **real merge executor 는 기본 OFF**. activation false 시 절대 실행 0. dryrun_route 결과를 입력으로 받아 real merge decision artifact 만 생성. `real_merge_execute` 함수가 존재하더라도 activation + chair_authorization 부재 시 NO_OP. 실 GitHub write / gh pr merge / branch protection 우회 / admin override 코드 경로 0.

## 필수 구현 (회장 verbatim 15항목)

### 신규 모듈
1. `utils/real_merge_hooks.py` (또는 동등 신규 모듈) — `real_merge_execute()` 순수함수 + dryrun→real switch
2. `utils/activation_flag_validator.py` — `ACTIVATION_FLAG_DEFAULT=False` 하드코딩 상수 + env var 검사 + import time assertion
3. `utils/chair_authorization_validator.py` — `anu.chair_merge_authorization.v1` JSON validator (verbatim token signature · TTL 검증)
4. `utils/gate_snapshot_validator.py` — `pre_merge_gate_snapshot.json` 11종 검증 + 5분 TTL 단언

### artifact writers (canonical_root 기준 atomic write — task-2636 resolver 사용)
5. `merge_decision.json` writer (schema `real_merge.decision.v1`)
6. `pre_merge_gate_snapshot.json` writer (schema `real_merge.pre_gate_snapshot.v1`)
7. `merge_execution_result.json` writer (schema `real_merge.execution_result.v1`)
8. `post_merge_smoke_result.json` **schema 만 준비** (writer 구현은 본 task 범위 외 — pilot 단계에서 구현)

### fixture 신규 (7 시나리오 + 권장 PASS path 1)
`tests/fixtures/real_merge_wiring/<scenario>/{evidence.json, expected.json, PROVENANCE.md}` (8×3 = 24 files):
9. `no_op_no_authorization` — activation_flag=True · chair_authorization 부재 → NO_OP_NO_AUTHORIZATION
10. `would_merge_but_disabled` — dryrun WOULD_MERGE · activation_flag=False → NO_OP_FLAG_DISABLED
11. `stale_snapshot` — snapshot TTL > 5분 → NO_OP_STALE_SNAPSHOT
12. `chair_auth_expired` — expires_at_kst 경과 → NO_OP_NO_AUTHORIZATION (expired)
13. `admin_override_required` — gate_snapshot.admin_override_required=true → NO_OP_GATE_FAIL + CHAIR_REPORT
14. `blocking_secret_detected` — NET_NEW_IDENTIFIER_EXPOSURE > 0 → NO_OP_GATE_FAIL + CHAIR_REPORT
15. `post_smoke_fail_report_only` — REAL_MERGE_DONE 가정 후 smoke 실패 → POST_MERGE_SMOKE_FAILED + 자동 rollback 0 + CHAIR_REPORT
16. (권장 추가) `pass_path_inert_artifact_only` — 11종 gate 통과 + auth 통과 + activation_flag=True 이지만 **실제 merge 호출은 가짜 runner (subprocess injection)** → REAL_MERGE_DONE artifact 만 생성. 실 GitHub 호출 0.

### regression (4종 권장)
- `tests/regression/test_real_merge_executor_no_op_paths.py` — 7 NO_OP fixture finalize_result 단언 + 실 subprocess 호출 0
- `tests/regression/test_chair_authorization_validator.py` — verbatim signature · TTL · pr_numbers/head_shas 매칭 단언
- `tests/regression/test_gate_snapshot_validator.py` — 11종 gate 측정 + STALE_SNAPSHOT TTL 단언
- `tests/regression/test_real_merge_inert_pass_path.py` — pass path 에서도 실 GitHub 호출 0 + artifact 4종 (3 writer + 1 schema) 정합 단언

### (선택)
- `tests/fixtures/real_merge_wiring/INDEX.md`
- `dispatch/__init__.py` import 1줄 추가 (real_merge_hooks 결선)

## 안전 불변식 (spec §15 + 회장 verbatim)
- `ACTIVATION_FLAG_DEFAULT = False` (hardcoded · import time assertion · 런타임 변경 0)
- chair_authorization 부재 → NO_OP_NO_AUTHORIZATION (fail-closed)
- 실 `gh pr merge` 호출 0 (subprocess wrapper injection 만 · regression 에서 mock)
- admin override CLI 옵션 (`--admin`) 호출 코드 경로 0 (정적 가드)
- branch protection 우회 0
- non-admin merge path 만 (regression 단언)
- ANU key `c119085addb0f8b7` 단일 출처 유지 (변경 0)
- envelope UTF-8 ≤3900 bytes 유지
- live cokacdir 실호출 0 (monkeypatch/dry-run)
- forbidden paths 11+종 정적 가드 (spec §14):
  - `utils/replacement_pr_runner.py` · `scripts/finish-task.sh`
  - `utils/merge_ready_classifier.py` · `utils/merge_ready_dryrun_executor.py`
  - `utils/callback_envelope_schema.py` · `utils/anu_callback_registrar.py`
  - `utils/canonical_root_resolver.py` · `utils/anu_collector_action_trigger.py`
  - `dispatch/finalize_hooks.py` · `.tasks/` · `tests/fixtures/` · `tests/regression/`
  - 무수정 + real_merge_execute 가 PR 변경 파일 목록 사전 점검 시 위 path 포함 → NO_OP_FORBIDDEN_PATH + CHAIR_REPORT

## 필수 regression
- 신규 4 regression PASS
- 기존 canonical-root 63 + callback consistency 40 + task-2635 helper 68 + baseline (shadow 156 + dryrun 58 + classifier 50) = 435 유지
- full new fail 0 (3 pre-existing test_stash_origin_audit_compat 무관)
- subprocess 실호출 0 (monkeypatch 강제)

## 자동수렴 (spec §11)
- Gemini medium/style/quality + expected_files 내부 + Critical7 0 + credential expansion 0 → 자동수렴
- expected_files 내부 non-critical HIGH 자동수렴, 동일 함수 HIGH 반복 시 LOOP_BOUNDARY → 회장 보고
- 회장 보고 트리거: Critical7 / credential expansion / expected_files 밖 / admin override 필요 / post-merge smoke 실패

## 금지 (회장 verbatim)
- 실제 merge 실행 금지
- gh pr merge 호출 금지
- push/PR 생성 금지
- branch protection 우회 금지
- admin override 자동화 금지
- low-risk pilot 실행 금지 (별도 회장 승인 task)
- NL intake 코드 구현 금지
- foreign dirty 정리 금지
- replacement_pr_runner 수정 금지
- finish-task.sh 수정 금지
- production service task 와 혼합 금지
- merge_ready_classifier / merge_ready_dryrun_executor 본체 수정 금지

## expected_files (task-2637 범위)
신규:
- `utils/real_merge_hooks.py`
- `utils/activation_flag_validator.py`
- `utils/chair_authorization_validator.py`
- `utils/gate_snapshot_validator.py`
- `utils/real_merge_artifact_schema.py` (4 writer schema 정의 + post_smoke schema-only)
- `tests/fixtures/real_merge_wiring/<8 시나리오>/{evidence.json,expected.json,PROVENANCE.md}` (24 files)
- (선택) `tests/fixtures/real_merge_wiring/INDEX.md`
- `tests/regression/test_real_merge_executor_no_op_paths.py`
- `tests/regression/test_chair_authorization_validator.py`
- `tests/regression/test_gate_snapshot_validator.py`
- `tests/regression/test_real_merge_inert_pass_path.py`

수정 (최소 결선):
- `dispatch/__init__.py` — import 1줄 추가 (real_merge_hooks 결선)

총 ~35 files. **프로덕션 영향**: dispatch/__init__.py 1줄 + 신규 helper 5. **활성화 코드 경로 0** (default OFF).

## finalize 프로토콜 (★ BOT App token 부재 — 로컬 한정 · spec §13)
1. base = 최신 origin/main 88a1f2b0 clean worktree
2. 신규 helper 5 + fixture 24 + regression 4 + dispatch/__init__.py 1줄 수정 전부 PASS + full new-fail 0 + 기존 435 유지
3. **로컬 commit만** (push/PR/merge 금지). finish-task.sh project_path 없이 로컬 종결
4. ANU normal completion callback — task-2635+1/task-2636 registrar 패턴 그대로 사용. envelope 5축 + 6번째 canonical_root 명시
5. envelope 정합: REGISTERED + schedule_id non-null + DELIVERED + UNCONFIRMED + canonical_root=/home/jay/workspace
6. callback envelope UTF-8 ≤3900 bytes
7. executor 시작/종료 ts·로컬 commit SHA 명기

## frozen anchor (D-SPEC-EXACTNESS · spec §17)
- ANCHOR-1: "본 task = 코드화/비활성 구현까지만 · 실제 merge 실행 금지 · activation false default"
- ANCHOR-2: "activation_flag default=False hardcoded · chair_authorization 부재 시 NO_OP_NO_AUTHORIZATION · 둘 다 True 일 때만 11종 gate 재검증"
- ANCHOR-3: "non-admin merge 만 허용 · admin override 코드 경로 0 · gh pr merge 실호출 0 (subprocess injection mock)"
- ANCHOR-4: "dryrun WOULD_MERGE → real merge_decision artifact 매핑 byte-equal (verdict→action 동일)"
- ANCHOR-5: "artifact 3 writer + post_smoke schema-only · canonical_root 기준 atomic write · dedupe (pr+head_sha)"
- ANCHOR-6: "forbidden paths 11+종 정적 가드 (replacement_pr_runner/finish-task.sh/merge_ready_classifier/merge_ready_dryrun_executor/callback_envelope_schema/anu_callback_registrar/canonical_root_resolver/anu_collector_action_trigger/dispatch_finalize_hooks/.tasks/tests/fixtures/tests/regression)"
- ANCHOR-7: "low-risk pilot 실행 본 task 범위 외 — 별도 회장 결정"
- ANCHOR-8: "callback governance stack production verified (88a1f2b0) 와 별개 wiring layer · 활성화는 다음 회장 승인"
