# task-2729+15 — FINISH_TASK_CODE_ROOT_EVIDENCE_ENV_FIX (finish-task.sh-only, activation 0)

## 레벨
Lv.3 (production infra fix — finish-task.sh evidence-root env 전파 + dirty-scope. git_evidence 무수정. production activation 아님)

## 발번 주석
FINISH_TASK_GIT_EVIDENCE_CODE_ROOT_RESOLUTION_FIX 재스코프(A안, finish-task.sh-only). lineage 연속 위해 **task-2729+15** 발번(회장 확인 요망).

## 한 줄 목표
CODE_ROOT 격리 작업(#188 B-alignment: 작업이 별도 worktree branch 에만 commit)에서 finish-task 의 normal callback/finalize 가 막히는 구조를 **finish-task.sh 단독 수정**으로 정상화한다: (1) QC subprocess 에 PROJECT_PATH/WORKTREE_PATH(=selected evidence root=CODE_ROOT) **명시 export** → git_evidence 가 canonical fallback 대신 CODE_ROOT 해석 (2) GIT-GATE dirty-scope 를 CODE_ROOT 기준으로 분리 → canonical 무관 dirty 가 CODE_ROOT clean task finalize 를 false-block 하지 않게. **git_evidence.py 무수정. callback prereg root 무수정. activation 0.**

## 배경 실측 (ANU read-only 진단, 단일 소스)
- 진단: `memory/plans/p0b-pickup/finish_task_git_evidence_coderoot_commit_exists_blocker_diagnosis_260608.md`.
- **git_evidence.py(9 사본 전부)는 이미 4단계 evidence-root resolution 보유**(`_resolve_project_dir_with_source`: A=env PROJECT_PATH/WORKTREE_PATH / B=task-timers worktree_path / C=task파일 경로 / D=fallback) + COMMIT_EXISTS `git log --all --fixed-strings --grep` 사용. ⇒ **git_evidence 수정 불필요**.
- **진짜 결함**: `finish-task.sh` 가 QC subprocess(`python3 $QC_SCRIPT --gate --task-id ...`, 약 line 371~374) 에 PROJECT_PATH/WORKTREE_PATH 를 **export 0건** → git_evidence 가 case (D) canonical fallback → CODE_ROOT 작업 evidence 오판.
- GIT-GATE: `PROJ_DIR=${PROJECT_PATH:-$WORKSPACE}`(line ~647). canonical 무관 dirty 1321 → EXTERNAL_DIRTY block(+13). CODE_ROOT worktree 는 clean.
- 9-사본 fan-out 회피 위해 git_evidence 미편집(회장 결정). callback prereg 의 `canonical_root==CANONICAL_ROOT` 계약(+39)도 무수정(Phase B 분리).
- ★ 로드 경로 사실: finish-task.sh:364-368 = 팀별 qc_verify(`teams/${TEAM}/qc/qc_verify.py`) 존재 시 그것 사용 → 팀별 verifiers/git_evidence.py 로드. 따라서 fix 는 **finish-task 가 그 subprocess 에 env 전파**하면 팀 사본 수정 없이 적용됨.

## 수정 (finish-task.sh 단독)
### A. QC subprocess 에 evidence root env 전파
- finish-task.sh 가 selected evidence root(우선순위: 인자 PROJECT_PATH → 자동탐지 _AUTO_PROJECT_PATH → WORKTREE_PATH) 를 결정하고, **QC 호출 시 `PROJECT_PATH=<root> WORKTREE_PATH=<root> python3 $QC_SCRIPT ...` 로 export/전파**. CODE_ROOT 격리 작업이면 root=CODE_ROOT.
- root 우선순위 고정: ① 명시 인자 PROJECT_PATH ② task-timers worktree_path/project_path ③ 자동탐지(.git 보유 worktree) ④ fallback canonical. **선택된 root 를 git_evidence 가 case A 로 받게** export.
### B. GIT-GATE dirty-scope 분리
- GIT-GATE dirty 검사 PROJ_DIR 가 selected evidence root(CODE_ROOT) 기준이 되도록 + EXTERNAL_DIRTY 분류가 CODE_ROOT-격리 clean worktree finalize 를 **false-block 하지 않게**(+13 해소). 단 **CODE_ROOT own dirty / forbidden / expected 초과 / stale·behind·diverged base 는 fail-closed 유지**.
### C. backward-compat
- 일반 canonical-path task(PROJECT_PATH 미지정·canonical 작업)는 **기존 동작 100% 동일**(env 전파가 canonical 이면 현행과 동일 결과). 회귀로 증명.

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "scripts/finish-task.sh"
    - "tests/regression/test_finish_task_coderoot_evidence_env_fix_2729p15.py"
    - "memory/reports/task-2729+15.md"
    - "memory/plans/p0b-pickup/finish_task_coderoot_evidence_env_fix_design_260608.md"
    - "memory/events/task-2729+15.*"
    - "memory/tasks/task-2729+15-finish-task-coderoot-evidence-env-fix.md"
  read_only_reference:
    - "teams/shared/verifiers/git_evidence.py (resolution 참조 — 무수정)"
    - "teams/dev4/qc/verifiers/git_evidence.py (로드 경로 참조 — 무수정)"
    - "teams/shared/qc_verify.py / teams/dev*/qc/qc_verify.py (무수정)"
    - "memory/plans/p0b-pickup/finish_task_git_evidence_coderoot_commit_exists_blocker_diagnosis_260608.md"
  forbidden_paths:
    - "/home/jay/workspace (canonical working tree — reset/clean/stash/switch 금지)"
    - "teams/shared/verifiers/git_evidence.py"
    - "teams/dev*/qc/verifiers/git_evidence.py"
    - "scripts/harness/v36/callback_preregistration.py (callback prereg root 무수정)"
    - "dispatch/normal_fallback_callback_helper.py (canonical_root 계약 무수정)"
    - "memory/state/**"
    - "memory/events/task-*.result.json (canonical result.json 이동·삭제·quarantine 금지)"
    - "memory/events/task-*.g4-fix-loop-count (G4 reset 금지)"
    - "deploy/systemd/**"
    - "dispatch.py"
    - "task-2716 branch (수정 금지)"
```

## EXPECTED FILES (정확히 4 — 초과 시 즉시 HOLD_FOR_CHAIR)
1. `scripts/finish-task.sh` — QC subprocess evidence-root env 전파 + GIT-GATE dirty-scope(CODE_ROOT 격리 false-block 해소, fail-closed 유지)
2. `tests/regression/test_finish_task_coderoot_evidence_env_fix_2729p15.py` — 회귀(isolated temp)
3. `memory/reports/task-2729+15.md` — 결과 + 필수검증 16
4. `memory/plans/p0b-pickup/finish_task_coderoot_evidence_env_fix_design_260608.md` — 설계
- (필요 시 evidence 1개 — 단 4+1=5 초과 금지)
- ★ git_evidence.py(9 사본) / callback prereg / normal_fallback_callback_helper **무수정**. 수정 필요 판명 시 즉시 HOLD_FOR_CHAIR.

## 필수 검증 (회장 verbatim 16, isolated temp)
1. QC subprocess 에 PROJECT_PATH/WORKTREE_PATH 실제 전달 확인. 2. CODE_ROOT commit → selected evidence root 기준 COMMIT_EXISTS PASS. 3. canonical HEAD lineage 에 commit 없어도 selected root 기준 PASS. 4. +13 EXTERNAL_DIRTY 재현 후 PASS. 5. +14 COMMIT_EXISTS_RESOLUTION_GAP 재현 후 PASS. 6. canonical dirty 1321 이 CODE_ROOT clean finalize false-block 안 함. 7. CODE_ROOT own dirty → fail. 8. forbidden path → fail. 9. expected_files 초과 → fail. 10. stale/behind/diverged worktree → fail. 11. 일반 canonical-path finalize backward-compat PASS. 12. raw key 0. 13. ACTIVE=false. 14. systemd enable 0. 15. activation_epoch absent. 16. canonical result.json mutation 0.

## 금지 (회장 verbatim)
1. git_evidence.py 수정  2. teams/devN/qc/verifiers/git_evidence.py 9 사본 수정  3. callback prereg root 변경  4. systemctl enable  5. ACTIVE=true  6. canonical activation_epoch  7. real ANU spawn  8. canonical reset/clean/stash -u/checkout -f  9. task-2716 수정  10. live memory artifacts 이동·삭제  11. canonical result.json 이동·삭제·quarantine  12. G4 reset  13. 수동 .done  14. PR push/merge/comment 자동  15. expected_files 초과
- 모든 검증 isolated temp. canonical 무손상.

## 이번 라운드 범위
- 구현 + isolated verify + PR_READY_CANDIDATE 까지. PR 생성/CI·Gemini gate/merge/activation = 별도 승인 전까지 0.
- ★ 재귀 주의: 본 task 도 finalize 시 동일 블로커 가능 → 봇은 worktree 의 *수정된* finish-task 로 self-dogfood 시도, 막히면 EXTERNAL_DIRTY/COMMIT_EXISTS 로 분리 기록(robust callback 성공 과장 금지). ANU 가 CODE_ROOT diff 독립검증으로 회수.

## 완료 판정
- 필수검증 16 PASS → **`PR_READY_CANDIDATE_FINISH_TASK_CODE_ROOT_EVIDENCE_ENV_FIX_ACTIVE_FALSE`**(로컬 verify, PR 미생성).
- git_evidence 수정 필요 / 9 사본 수정 필요 / callback prereg root 변경 필요 / expected_files 초과 / canonical reset·clean·stash 필요 / 수동 .done 필요 / real spawn 필요 / ACTIVE=true·systemd enable·activation_epoch 필요 / task-2716 수정 필요 → **`HOLD_FOR_CHAIR`**.
- ★ PR·activation 별도 회장 승인 전까지 금지.

## doctrine
직접 코딩 금지(ANU)/봇 위임 / canonical·task-2716 무손상 / isolated temp / git_evidence·callback prereg 무수정 / backward-compat 필수 / production code 변경이므로 회귀 강건 / activation 0 / raw key 0 / same-PR push 금지·bot trigger 금지·long polling 금지.
```yaml
callback_envelope_byte_limit: 3900
callback_collector_role: ANU
callback_owner_key_source: ".env.keys COKACDIR_KEY_ANU (sealed, literal 출력 0)"
```
