# [ROUND-1 BOUNDED FIX] task-2726+1 — PR #171 fresh HIGH 2건 수정 (회장 승인 2026-06-03)

## Situation
PR #171(head `520198e2`) 인간 OWNER `/gemini review`에서 fresh HIGH 2건 식별(둘 다 expected_files 내부, 코드 직접대조 유효):
- **HIGH-1** `test:28` — `REPO = Path("/home/jay/workspace/.worktrees/task-2726-dev3")` 로컬 절대경로 하드코딩. task-2726이 없애려던 WORKSPACE_ROOT_HARDCODE doctrine을 테스트가 재도입 → 타 환경/CI 실패.
- **HIGH-2** `finish-task.sh:78` — `_emit_worktree_unresolved`의 `python3 -c` heredoc에 `'reason':'$reason'` 직접 보간. reason에 작은따옴표 포함 시 Python SyntaxError → WORKTREE_UNRESOLVED safety-net marker 생성 실패.

## Complication
safety-net(WORKTREE_UNRESOLVED marker)이 정상 reason에는 동작하나, 실제 운영 중 error reason에 작은따옴표/특수문자가 들어오면 marker가 깨져 fail-closed 방어선이 무력화. 테스트의 로컬경로 하드코딩은 CI/타 환경 재현 불가.

## Question
expected_files 2파일 내부 surgical fix로 (1) 테스트 이식성 확보 (2) 어떤 reason 문자열에서도 marker crash 0 을 어떻게 보장하는가?

## Answer (수정 내용)

### HIGH-1 — test REPO 동적 계산
- `tests/regression/test_finish_task_worktree_isolation_2726.py:28`
- `REPO = Path("/home/jay/workspace/.worktrees/task-2726-dev3")` → `REPO = Path(__file__).resolve().parents[2]`
  - `tests/regression/<file>` 기준 parents[2] = repo 루트. 로컬 절대경로 0, 타 환경/CI 이식 가능.

### HIGH-2 — finish-task.sh `python3 -c` sys.argv 전달 (heredoc injection 제거)
- `scripts/finish-task.sh` 3개 함수 동일 벡터 일괄 교정(회장 "동일 injection 벡터면 함께" 권장 반영):
  1. `_emit_worktree_unresolved` (핵심): `$EVENTS_DIR/$tid/$reason` 직접 보간 제거 → `events_dir, tid, reason = sys.argv[1:4]`, 호출부 `... "$EVENTS_DIR" "$tid" "$reason"`.
  2. `_resolve_task_worktree`: `workspace='$WORKSPACE'; tid='$tid'` 인라인 보간 제거 → `sys.argv` 수신.
  3. `_task_expects_worktree`: `'$tid'`/`open('$WORKSPACE...` 보간 제거 → `sys.argv` 수신.
  - 어떤 reason(작은따옴표/공백/세미콜론/퍼센트/유니코드/빈문자)에서도 marker 생성 crash 0.

### 회귀 테스트 추가 (모리건)
- `test_emit_marker_with_single_quote_reason`: 작은따옴표 reason → marker 생성 + 원문 보존 검증(HIGH-2 직접 회귀).
- `test_emit_marker_with_empty_and_special_reason`: 빈문자/유니코드/작은따옴표·세미콜론 4케이스 crash 0 + 원문 보존.
  - 주: 헬퍼 `run_func`가 인자를 큰따옴표로 감싸므로 command-substitution(`$(...)`/백틱)·큰따옴표는 bash 레벨에서 변형됨(하니스 한계, finish-task.sh 무관) → 실제 HIGH-2 벡터인 작은따옴표 위주로 검증.

## 수정 파일 (expected_files 2개 내부)
1. `scripts/finish-task.sh` — 3함수 sys.argv 전달
2. `tests/regression/test_finish_task_worktree_isolation_2726.py` — REPO 동적 + 회귀 2건 추가

## 회장 10 검증 결과 (전 항목 PASS)
1. 기존 22 regression 유지 → **24 passed** (22 + 신규 2) ✓
2. 로컬 절대경로 grep 0 (`/home/jay/...task-2726-dev3` in test = 0, goal_assertion PASS) ✓
3. 작은따옴표 reason marker 생성 PASS (신규 회귀 + L1 smoke) ✓
4. WORKTREE_UNRESOLVED marker 생성 PASS (정상 reason, 기존 test 유지) ✓
5. `FINISH_TASK_WORKTREE_STRICT="${FINISH_TASK_WORKTREE_STRICT:-0}"` default-off 유지 ✓
6. `git diff --name-only origin/main` = expected_files 2파일 내부 ✓
7. forbidden 0 (diff에 forbidden_paths 없음) ✓
8. ANU key literal(`c119085...`) — finish-task.sh/test 양쪽 0 ✓
9. shared main/dev4 branch 개입 0 (task/task-2726-dev3 단일 브랜치) ✓
10. `.done` 위조 0 — finish-task.sh만이 완료 경로 ✓
- smoke: `pytest ... -q` → 24 passed · `bash -n scripts/finish-task.sh` → rc=0 ✓

## L1 스모크테스트 결과 (필수)
- **서버 재시작**: 해당없음 (백엔드 bash/python CLI 함수)
- **API 응답 확인**: 해당없음
- **실동작 검증 (실제 실행)**: finish-task.sh에서 `_emit_worktree_unresolved` 함수 추출 → 실제 bash 실행, reason=`git-gate: can't resolve PROJECT_PATH for 'worktree' task`(작은따옴표 2개) 전달 → rc=0, marker JSON 생성, `reason` 필드 작은따옴표 원문 그대로 보존 확인(L1 SMOKE PASS). 구 코드라면 SyntaxError로 marker 미생성될 케이스.
- **스크린샷**: 해당없음 (CLI)

## Git / 머지 판단
- **commit**: `041989e4` (non-force push, 520198e2..041989e4 fast-forward, PR #171 갱신)
- **머지 필요**: Yes — 단 **회장 승인 전 merge 금지 (MERGE_READY_CANDIDATE)**
- **브랜치**: task/task-2726-dev3 · **워크트리**: /home/jay/workspace/.worktrees/task-2726-dev3 · **PR**: #171
- **머지 의견**: bounded surgical fix, 24 회귀 PASS, diff 2파일, forbidden/ANU key 0, STRICT default-off 보존. 새 head OWNER `/gemini review` → CI GREEN + fresh unresolved HIGH/CRITICAL 0 시 MERGE_READY_CANDIDATE.

## 모델 사용 기록
- 루(백엔드, finish-task.sh): **sonnet** — 일반 로직 수정
- 모리건(테스터, test 파일): **sonnet** — 테스트 코드(전략/분석 아님, haiku 미사용)
- 팀장(다그다, Opus): 설계/분배/검증/L1 smoke/통합 커밋만 수행(직접 코딩 위임)

## 비고 (doctrine 준수)
- merge 미수행(회장 승인 전 금지) · 봇 `/gemini review` 미트리거(인간 OWNER 1회 doctrine) · amend/force push 금지 준수(non-force fast-forward).
- shared main stash/reset/clean/delete 0 · dev4 branch 미개입 · task-2725/2727 미혼입 · PR #169 미커밋.
- 새 HIGH/CRITICAL 발생 0 (CHAIR_REQUIRED 트리거 없음).
- ANU normal callback cron 강제 등록(collector_role=ANU, 독립 ANU key) — 본 task 종료 시 등록.
