# task-2639 — real_merge_hooks chair_authorization snapshot 교차검증 정책 수정 (real merge 실행 0)

- Level: Lv.3 (real merge wiring 정책 정정 · activation false default 유지)
- 담당: dev6 페룬
- base: origin/main **fa72e25a** (PR #140 real merge wiring OFF-mode 머지 반영분)
- 단일소스 spec: `memory/specs/system_real_merge_hooks_snapshot_crossref_spec_260523.md`
  - sha256: `12b8af006913833596562c55ab9a0acca935830be90c5f17f2af4b7e1e632621`
  - 정독 전 sha256sum 검증 필수
- 회장 D안 결정 (2026-05-23): PR #141 pilot NO_OP_FORBIDDEN_PATH 사고 → snapshot 교차검증 도입

## 목표
real_merge_hooks Step 0 흐름에 chair_authorization expected_files_snapshot 교차 검증 도입. forbidden prefix 보안 가드 보존 + snapshot exact match 만 통과. broad allowlist 금지.

## 필수 구현 (회장 verbatim 10항목 정본 → spec §2)
1. forbidden prefix 검사 전 snapshot 로드
2. changed_files 부분집합 단언
3. PR/head_sha exact 일치 단언
4. snapshot 외부 forbidden → NO_OP_FORBIDDEN_PATH 유지
5. snapshot 내부 production/secret/admin override → CHAIR_REQUIRED
6. .tasks/locks/* sanctioned 분리 기록
7. tests/fixtures doc-only snapshot match 통과
8. allow_reason merge_decision.json 명시
9. broad prefix allowlist 금지
10. forbidden 보안 의미 유지

## 신규 모듈
- `utils/snapshot_crossref_validator.py` (Step 0b/0c/0d 통합)

## 수정 (최소 결선)
- `utils/real_merge_hooks.py` Step 0 정정 + schema v1→v2
- `utils/real_merge_artifact_schema.py` v2 필드 (`allow_reason` + `snapshot_crossref`)

## 신규 enum
- `NO_OP_AUTH_MISMATCH` (pr/head_sha 불일치)
- `CHAIR_REQUIRED_PRODUCTION_IN_SNAPSHOT`
- `CHAIR_REQUIRED_BLOCKING_SECRET_IN_SNAPSHOT`
- `CHAIR_REQUIRED_ADMIN_OVERRIDE_REQUIRED`

## fixture 7 시나리오 × 3 = 21 (회장 verbatim · spec §6 정본)
- `fixture_in_snapshot_pass_candidate` → PASS candidate + allow_reason 기록
- `fixture_in_snapshot_mismatch_no_op` → NO_OP_FORBIDDEN_PATH
- `fixture_wrong_head_sha` → NO_OP_AUTH_MISMATCH
- `sanctioned_lock_separated` → 분리 기록
- `production_in_snapshot_chair_required` → CHAIR_REQUIRED_PRODUCTION_IN_SNAPSHOT
- `blocking_secret_in_snapshot_chair_required` → CHAIR_REQUIRED_BLOCKING_SECRET_IN_SNAPSHOT
- `admin_override_required_chair_required` → CHAIR_REQUIRED_ADMIN_OVERRIDE_REQUIRED

## 신규 regression 2
- `tests/regression/test_snapshot_crossref_validator.py` (7 fixture parametrized)
- `tests/regression/test_real_merge_hooks_v2_step0_flow.py` (Step 0 흐름 + v2 schema)

## 안전 불변식 (spec §6)
- forbidden prefix 보안 의미 유지 · broad allowlist 금지
- ANU key c119085addb0f8b7 단일 출처 유지
- live cokacdir/subprocess 실호출 0 (regression mock)
- 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 / activation_flag_validator / chair_authorization_validator / gate_snapshot_validator / dispatch/finalize_hooks / dispatch/__init__ **무수정**
- real_merge_hooks 와 real_merge_artifact_schema 만 정정
- expected_files 외부 수정 0
- BLOCKING_SECRET 0

## regression
- 신규 2 PASS
- 기존 real_merge no_op 8 + 4 wiring + canonical-root 63 + callback consistency 40 + task-2635 helper 68 + baseline 264 = **476 유지**
- full new fail 0

## 자동수렴
- Gemini medium/style + expected_files 내부 → 자동수렴
- 동일 함수 HIGH 반복 시 LOOP_BOUNDARY → 회장 보고

## 금지 (회장 verbatim)
- PR #141 직접 merge 금지 (정책 수정 머지 후 재검증)
- 기존 chair_authorization 재사용 금지 (EXPIRED_UNUSED 처리됨)
- real auto-merge batch activation 금지
- admin override 금지
- branch protection 우회 금지
- foreign dirty 정리 금지
- replacement_pr_runner 수정 금지
- finish-task.sh 수정 금지
- NL intake 코드 구현 금지
- broad prefix allowlist 도입 금지

## expected_files (~28)
- utils/snapshot_crossref_validator.py (신규)
- utils/real_merge_hooks.py (Step 0 정정 · schema v1→v2)
- utils/real_merge_artifact_schema.py (v2 필드)
- tests/fixtures/snapshot_crossref/<7 시나리오>/{evidence,expected,PROVENANCE} (21 files)
- (선택) tests/fixtures/snapshot_crossref/INDEX.md
- tests/regression/test_snapshot_crossref_validator.py
- tests/regression/test_real_merge_hooks_v2_step0_flow.py

## finalize 프로토콜 (★ BOT App token 부재 — 로컬 한정)
1. base = origin/main fa72e25a clean
2. 신규 helper 1 + fixture 21 + regression 2 + real_merge_hooks 정정 + artifact_schema 정정 PASS · 기존 476 유지 · new fail 0
3. **로컬 commit만**. push/PR/merge 금지. finish-task.sh project_path 없이 로컬 종결
4. ANU normal callback — registrar 패턴 그대로 · envelope 5축 + canonical_root 명시 · REGISTERED + schedule_id non-null + DELIVERED + UNCONFIRMED
5. envelope ≤3900 bytes
6. executor 시작/종료 ts + 로컬 commit SHA 명기

이후 ANU: 적층 → push → PR open → Gemini 자동수렴 → 회장 보고 → 회장 merge 승인 → 정책 수정 merge 후 새 chair_authorization 재발급 → B1 pilot 재시도

## frozen anchor
- ANCHOR-1: "Step 0 흐름 (input→auth_match→snapshot_crossref→sanctioned_split→existing_gates)"
- ANCHOR-2: "forbidden prefix 보안 가드 유지 · snapshot exact match 만 통과 · broad allowlist 금지"
- ANCHOR-3: "schema v1→v2 bump · allow_reason + snapshot_crossref 필드 추가"
- ANCHOR-4: "production/secret/admin override 검출 시 CHAIR_REQUIRED 격상 (snapshot 포함 무관)"
- ANCHOR-5: "sanctioned (.tasks/locks/) 분리 기록"
- ANCHOR-6: "real_merge_hooks/real_merge_artifact_schema 만 정정 · 나머지 wiring stack 무수정"
- ANCHOR-7: "PR #141 직접 merge 금지 · 기존 chair_authorization EXPIRED · 새 발급은 정책 머지 후"
