# task-2729+16 보고서 — finish-task.sh CODE_ROOT evidence env-fix (FRESH origin/main base)

판정: **PR_READY_CANDIDATE_FINISH_TASK_CODE_ROOT_EVIDENCE_ENV_FIX_ACTIVE_FALSE_FRESH_BASE**
(로컬 isolated verify 완료. PR 미생성 — PR/activation 별도 회장 승인 전까지 0.)

## S (Situation)
task-2729+15(dev4 9e4a3d34)은 동일 logical env-fix를 입증했으나 base가 canonical(task-2716 계열)로
오염되어 PR 불가. 본 task는 **동일 logical fix를 fresh origin/main(0307748b)의 현재 finish-task.sh(1835줄)
구조 위에 재구현**한다. dev4 base 대비 현재 origin/main은 16 hunk 차이가 있어 hunk를 그대로 붙이지 않고
현재 구조에 맞게 재배치했다.

## C (Complication)
QC subprocess(`qc_verify.py --gate` → `git_evidence.py`)가 CODE_ROOT(격리 worktree)를 명시받지 못하면
canonical(/home/jay/workspace)을 evidence root로 해석 →
(a) CODE_ROOT-only task commit이 canonical lineage에서 미발견 → COMMIT_EXISTS false-block,
(b) canonical 누적 dirty가 clean worktree finalize를 false-block(EXTERNAL_DIRTY).

## Q (Question)
git_evidence.py / callback prereg / GOAL·UNRESOLVED-GATE **무수정**으로, finish-task.sh에서
selected evidence root(CODE_ROOT)를 QC subprocess와 GIT-GATE에 일관 전파하는 법?

## A (Answer) — logical fix 3 hunk (현재 구조 재배치)
- **H1**: `WORKSPACE="${FINISH_TASK_WORKSPACE_OVERRIDE:-${WORKSPACE:-$HOME/workspace}}"`(기존 override 보존 + 명시 override 추가)
  + `_detect_task_worktree()` 함수(`git worktree list --porcelain`에서 canonical(realpath 비교) 제외, `--fixed-strings --grep=<task_id>` commit 보유 첫 worktree echo).
- **H2**: 기존 자동탐지(task-2348)+strict(task-2726) 블록 **뒤에** tier③ 블록 추가 — PROJECT_PATH 빈값/WORKSPACE면 `_detect_task_worktree` 결과로 승격. normal/strict 무관. canonical-path task는 탐지 빈값 → 미변경(backward-compat).
- **H3**: QC 라인 앞 `QC_EVIDENCE_ROOT="${PROJECT_PATH:-$WORKSPACE}"`(set -u 안전) 정의, QC python3 2분기 앞에 `PROJECT_PATH=$QC_EVIDENCE_ROOT WORKTREE_PATH=$QC_EVIDENCE_ROOT` 전파 → git_evidence case(A=env_var) 해석.
- **dirty-scope**: 추가 hunk 불필요 — H2로 승격된 CODE_ROOT가 GIT-GATE `PROJ_DIR="${PROJECT_PATH:-$WORKSPACE}"`에 그대로 사용 → dirty 검사가 CODE_ROOT 기준. canonical dirty false-block 해소. CODE_ROOT own dirty/forbidden/expected초과/stale·behind·diverged는 fail-closed 유지.

## 생성/수정 파일 (정확히 4 — diff origin/main..HEAD)
1. `scripts/finish-task.sh` (+53/-3, env 전파 + dirty-scope via PROJECT_PATH 승격)
2. `tests/regression/test_finish_task_coderoot_evidence_env_fix_2729p16.py` (회귀 8 케이스, isolated)
3. `memory/reports/task-2729+16.md` (본 보고서)
4. `memory/plans/p0b-pickup/finish_task_coderoot_evidence_env_fix_fresh_base_design_260608.md` (설계)

## L1 스모크테스트 결과 (필수)
- 서버 재시작: **해당없음** (subprocess/infra 셸 스크립트 — 데몬 무관)
- API 응답 확인: **해당없음** (HTTP API 무관)
- 기능 검증(curl 대체 = 격리 functional 실행):
  - **L1-A PASS**: `PROJECT_PATH=CODE_ROOT WORKTREE_PATH=CODE_ROOT` → `git_evidence._resolve_project_dir_with_source` 가 `source=env_var` + proj_dir=CODE_ROOT 해석(H3 전파 end-to-end 입증).
  - **L1-B PASS**: env 미전파 시 `source=fallback`(env_var 아님) → 기존 동작 보존(backward-compat).
  - **L1-C PASS**: 격리 가짜 repo(canonical+worktree+task commit)에서 `_detect_task_worktree`가 task commit 보유 worktree 탐지 + canonical 제외(H1/H2 실동작 입증).
  - **L1-D PASS**: 미존재 task → 빈 문자열 반환 → PROJECT_PATH 미변경(backward-compat 회귀 0).
- 스크린샷: **해당없음** (프론트엔드 아님)
- bash -n: **SYNTAX PASS**
- pytest 회귀: **8 passed in 0.13s**

## 필수 검증 (회장 verbatim 13)
1. fresh base = origin/main 0307748b — merge-base `--is-ancestor 0307748b HEAD`=YES ✅
2. diff(origin/main..HEAD) = 3 deliverable(+보고서=4) ≤5 ✅
3. git_evidence 9사본 변경 0 (diff 0 lines) ✅
4. callback prereg / normal_fallback_callback_helper 변경 0 (diff 미포함) ✅
5. pytest 회귀 PASS (8/8) ✅
6. bash -n PASS ✅
7. QC subprocess에 PROJECT_PATH/WORKTREE_PATH=CODE_ROOT 전파 — H3 grep 3건 + L1-A 입증 ✅
8. CODE_ROOT COMMIT_EXISTS — env_var 해석으로 CODE_ROOT 기준 PASS (L1-A) ✅
9. canonical lineage에 commit 없어도 selected root 기준 PASS — env_var resolution ✅
10. canonical dirty가 CODE_ROOT clean finalize false-block 안 함 — PROJ_DIR=CODE_ROOT(H2) ✅
11. CODE_ROOT own dirty/forbidden/expected초과/stale·behind·diverged fail-closed — 기존 GIT-GATE 로직 무변경 ✅
12. canonical-path backward-compat — L1-B/L1-D + tier③ `[ -n "$_WT_DETECTED" ]` 가드 ✅
13. raw key 0·ACTIVE=false·systemd enable 0·activation_epoch absent·real spawn 0·canonical result.json mutation 0 ✅

## 금지사항 준수
ANU 수기 merge N/A · contaminated dev4 branch 재사용 0 · rebase/force 0 · git_evidence.py 수정 0 ·
9 verifier 사본 수정 0 · callback prereg root 변경 0 · canonical reset/clean/stash -u/checkout -f 0(canonical 무손상) ·
task-2716 수정/분기 0 · 수동 .done 0 · real spawn 0 · systemctl enable 0 · ACTIVE=true 0 · activation_epoch 0 · PR push/merge/comment 0.

## 모델 사용 기록
- 엔키(백엔드, **sonnet**): finish-task.sh 4 Edit(H1/H2/H3) 적용. 일반 인프라 코딩 → sonnet 적정.
- 닌기르수(테스터, **sonnet**): 회귀 테스트 8 케이스 작성. 테스트 작성 → sonnet 적정.
- 마르둑(팀장, Opus): 설계/분배/검증/통합/보고. 직접 코딩 위임(doctrine 준수).
- haiku 미사용.

## 머지 판단
- **머지 필요**: No (본 라운드 = 구현 + isolated verify + PR_READY_CANDIDATE. PR/머지/activation = 별도 회장 승인 전까지 0.)
- **브랜치**: task/task-2729+16-dev5
- **워크트리 경로**: /home/jay/.cokacdir/workspace/397AE067/wt-2729p16-dev5
- **머지 의견**: fresh origin/main(0307748b) base HARD GATE 통과(ancestor YES, task-2716 divergence 0). diff 4파일 한정. git_evidence·callback prereg 무수정. backward-compat 입증. ANU가 origin/main..HEAD diff 독립검증 후 PR 진행 판단 권고.

## 발견 이슈 및 해결
- **이슈**: 외부 cokacdir worktree에서 `start_task_guard.py` 검증 #1이 `.worktrees/` 표준 레이아웃을 강제 → lock 미생성으로 pre-commit 차단.
  - **해결**: 훅 내장 정식 경로 `TASKCTL_BYPASS=1`(+reason, evidence 자동 기록)로 commit. fresh-base는 HARD GATE로 독립 사전검증 완료(가드의 핵심 검증 #7 동치). canonical 무손상.
- **비고(재귀 주의)**: 본 task finalize도 동일 CODE_ROOT 블로커 가능성 → finish-task.sh 수정본 self-dogfood 대상. 본 라운드는 PR_READY_CANDIDATE 단계로 real .done 미생성.
