# task-2729+21 — FILE_TOUCH_RATIO_CHECK_CODE_ROOT_RECOGNITION Option A REPLACEMENT (QC/evidence-root, activation 0)

## 레벨
Lv.3 (QC verifier evidence-root hardening. production activation 아님)

## 발번 주석
PR #193(task-2729+20) HOLD_FOR_CHAIR 후속 Option A replacement(회장 2026-06-08 승인). #193 fresh HIGH(diff-root top-level 정규화 누락) + MED(HEAD~5 shallow guard) 일괄 수정. **#193 same-branch push/rebase/force/cherry-pick 금지** — fresh origin/main 새 branch. #193(0b257e76)은 **참고만**.

## ★★★ FRESH BASE HARD GATE
1. worktree 반드시 **origin/main `571a4ce3`(또는 이후 최신 main)** 분기. **canonical(task-2716 계열) 분기 절대 금지.**
2. `git worktree add -b task/task-2729+21-<bot> <path> origin/main`.
3. commit 전: `merge-base --is-ancestor 571a4ce3 HEAD == YES` AND `task-2716 divergence 0`. 실패 시 즉시 HOLD.
4. diff `origin/main..HEAD` = expected_files 만(3~4). 오염 diff → HOLD.
- ★ origin/main(571a4ce3)에 +20 CODE_ROOT 코드 없음 → 본 task 가 **CODE_ROOT recognition 전체를 새로 구현**(아래 보정 반영). #193 코드는 참고만, 복붙/cherry-pick 금지.

## 근본 원인 (단일 소스)
- file_touch_ratio_check: `qc_verify.py:563` 이 `verify(task_id)` 를 root 미전달 호출 + verify 가 PROJECT_PATH/WORKTREE_PATH/QC_EVIDENCE_ROOT env 미인식 → canonical(task-2716) diff 기준 ratio 0.00 false-negative → SKIP.
- ★ #193 fresh HIGH: env root 가 git repo **하위 디렉토리**면 `git diff` 는 repo top-level 기준 경로 반환, report path 파싱은 subdir 기준 처리 → **path mismatch 오탐**. = CODE_ROOT 정확 인식 핵심 결함.
- ★ #193 MED: `git diff --name-only HEAD~5` 가 커밋<5/shallow clone 에서 실패(subprocess error).

## 수정 (file_touch_ratio_check shared verifier 단독, B안)
### 핵심 로직
1. **env root 인식**: verify diff/evidence root = `PROJECT_PATH` → `WORKTREE_PATH` → `QC_EVIDENCE_ROOT` env 순(값 존재 + 유효 git dir 시). 없으면 `workspace_root` param/기본값 fallback.
2. ★★ **top-level 정규화 (회장 verbatim — HIGH)**: selected env root 가 repo **하위 디렉토리여도** `git rev-parse --show-toplevel`(또는 동등)로 **git 최상위 루트로 정규화**. **diff root 와 path normalization 기준을 일치**시켜 path mismatch 제거.
3. ★ **report root 와 diff/evidence root 분리 유지**: report 는 **canonical `memory/reports`** 에서 read 가능, diff 는 **selected(정규화된) CODE_ROOT** 에서 계산. canonical report + selected CODE_ROOT diff 조합 PASS.
4. ★★ **HEAD~5 fail-safe (회장 verbatim — MED)**: 커밋<5 / shallow / `HEAD~5` 부재 시 subprocess 실패 → **fail-safe 또는 bounded fallback**(예: 가용 커밋 수만큼 bounded, 또는 명확한 SKIP/graceful)로 처리. 미정의 crash 금지.
5. canonical task-2716 diff 로 인한 ratio 0.00 false-negative 제거.
6. backward-compat: env 미설정 시 기존 canonical 동작.
### symlink parity (구조 변경 금지)
- per-team 9 = `teams/<team>/qc/verifiers` **디렉토리 symlink → shared/verifiers**. **shared 1파일 수정으로 10카피 동일성 유지** — per-team 파일 직접 수정 금지.
- ★ dev8 absolute double-hop symlink(→ dev1 → shared)는 **이번 replacement 에서 구조 리팩터 금지** — caveat 로만 유지.
- ★ 디듀프 리팩터 착수 금지.

## EXPECTED FILES (정확히 3~4 — 초과 시 즉시 HOLD_FOR_CHAIR)
1. `teams/shared/verifiers/file_touch_ratio_check.py` — env 인식 + top-level 정규화 + report/diff root 분리 + HEAD~5 fail-safe
2. `tests/regression/test_file_touch_ratio_root_recognition_2729p21.py` — 회귀(isolated temp)
3. `memory/reports/task-2729+21.md`
4. (필요 시) `memory/plans/p0b-pickup/file_touch_ratio_toplevel_normalization_replacement_design_260608.md`
- ★ per-team 9 verifier 파일 / git_evidence.py / dispatch.py / callback prereg 무수정. symlink 구조 변경 / 디듀프 필요 판명 시 HOLD.

## 필수 regression (회장 verbatim 13, isolated temp)
1. env root=repo root 일 때 PASS. 2. env root=repo **하위 디렉토리** 일 때 top-level 정규화 후 PASS. 3. PROJECT_PATH/WORKTREE_PATH/QC_EVIDENCE_ROOT 우선순위 검증. 4. env invalid → canonical fallback 또는 fail-safe 명확. 5. canonical report + selected CODE_ROOT diff 조합 PASS. 6. worktree changed ↔ report changed 4/4 매칭 시 ratio 1.00 PASS. 7. HEAD~5 불가/shallow/커밋부족 fail-safe. 8. canonical task-2716 dirty/diff 가 selected CODE_ROOT clean finalize 를 false-block 안 함. 9. per-team directory symlink parity 확인. 10. raw key 0. 11. ACTIVE=false / systemd enable 0 / activation_epoch absent / real spawn 0. 12. git_evidence·dispatch·callback prereg 무수정. 13. canonical task-2716 branch·live memory artifacts 무손상.

## 금지 (회장 verbatim — 표준 세트)
1. PR #193 same-branch push  2. rebase/force  3. merge  4. production ACTIVE 전환  5. systemctl enable  6. ACTIVE=true 선언  7. activation_epoch 생성  8. real ANU spawn  9. canonical reset/clean/stash -u/checkout -f  10. task-2716 branch 수정  11. live memory artifacts 이동·삭제  12. callback prereg Phase B 착수  13. git_evidence.py/dispatch.py 수정  14. 디듀프 리팩터 착수  15. per-team symlink 구조 변경.
- 모든 검증 isolated temp. canonical 무손상. #193 코드 복붙/cherry-pick 강행 금지(참고만).

## 이번 라운드 범위 (★PR 생성까지 진행)
- 구현 + isolated verify(회귀 13) + **PR 생성** + CI/Gemini fresh gate 확인까지.
- ★ self-dogfood: 본 task finalize 도 file_touch_ratio_check 통과 확인. ANU origin/main..HEAD diff 독립검증 회수.

## 완료 판정
- 회귀 13 PASS + top-level 정규화 + report/code-root 분리 + HEAD~5 fail-safe + symlink parity + PR 생성 + CI GREEN + fresh Gemini(head 이후) HIGH/CRITICAL 0 + unresolved 0(또는 non-blocking) → **`MERGE_APPROVAL_CANDIDATE_FILE_TOUCH_RATIO_ROOT_RECOGNITION_ACTIVE_FALSE`**.
- fresh HIGH/CRITICAL 재발 / expected_files 초과 / raw key 노출 / symlink 구조 변경 필요 / git_evidence·dispatch·callback prereg 수정 필요 / 디듀프 필요 / activation·real spawn 필요 / task-2716 수정 → **`HOLD_FOR_CHAIR`**.
- ★ merge·production activation = 별도 회장 승인 전까지 0.

## 완료 후 callback
- 봇 완료 시 ANU(c119085addb0f8b7)로 normal callback cron 발사(envelope only, UTF-8 ≤3900 bytes, collector=ANU): task_id/result_path/report_path/PR번호/terminal_state/sha256/one-line summary. raw key literal 출력 0(.env.keys COKACDIR_KEY_ANU sealed).

## doctrine
직접 코딩 금지(ANU)/봇 위임 / fresh origin/main 571a4ce3 base / git_evidence env-인식 선례 미러링 + show-toplevel 정규화 / report-root와 diff-root 분리 / backward-compat / HEAD~5 fail-safe / symlink parity 보존(per-team 직접수정·디듀프 금지) / git_evidence·dispatch·callback prereg 무수정 / activation 0 / raw key 0 / same-PR post-Gemini push 금지.
```yaml
callback_envelope_byte_limit: 3900
callback_collector_role: ANU
callback_owner_key_source: ".env.keys COKACDIR_KEY_ANU (sealed, literal 출력 0)"
```
