# task-2783+1 — PR #262 same-PR microfix (Gemini HIGH 정밀화, A안)

## 레벨
Lv2 (2파일 정밀 microfix + 테스트 재구성). 코드 작업. **PR #262 head에 커밋 추가**(신규 PR 금지).

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "utils/replacement_pr_runner.py"
    - "tests/regression/test_replacement_pr_runner_2510.py"
  forbidden_paths:
    - "utils/merge_queue_executor.py"
    - "utils/real_merge_hooks.py"
    - "scripts/finish-task.sh"
    - "scripts/gemini_evidence_verify.py"
    - "dispatch.py"
    - ".github/**"
    - ".claude/**"
    - ".env*"
    - "memory/state/**"
  commands:
    - "git"
    - "pytest"
    - "python3"
  merge_policy: "none"
  ttl_hours: 6
```

## 컨텍스트
PR #262(task-2783)에 Gemini **HIGH 1**(utils/replacement_pr_runner.py:~209 `EMPTY_OVERWRITE_REFUSED`가 정상 empty-file PR을 과차단) + MEDIUM 1(T17). 회장/GPT 판정 = **Gemini 권고대로 단순제거 아니라 정밀 guard 교체(A안)**. 기존 브랜치 `task/task-2783-dev3`(head 62ea27ae)에 커밋 추가.

## 작업 위치 (중요)
- 기존 worktree `/home/jay/workspace/.worktrees/task-2783-dev3`, 브랜치 `task/task-2783-dev3`에서 작업.
- 변경 후 커밋 → `git push origin task/task-2783-dev3`로 **PR #262 갱신**. **신규 PR 생성 금지 · merge 금지.**

## 수정 요구 (A안 — GPT verbatim)
**1. `utils/replacement_pr_runner.py::transplant_expected_files`**
- **`EMPTY_OVERWRITE_REFUSED` guard 제거**(과차단 — 정상 empty blob도 막음).
- **`GIT_SHOW_FAILED`(returncode != 0) 체크 유지** — git show 실패/소스 blob 없음은 계속 fail-closed(기존 파일 보존).
- **rc0 + stdout empty = 정상 empty blob으로 허용**(write 진행).
- **Guard 1 `TARGET_OUTSIDE_REPO_ROOT` 유지**(repo root 밖 resolve fail-closed).
- ★ **`cwd = repo_dir or str(WORKSPACE)` fallback은 이번 PR에서 건드리지 말 것**(repo_dir mandatory화 금지). 이유: `merge_queue_executor.py:1745`(forbidden·expected_files 밖)가 repo_dir 없이 호출 → mandatory화하면 깨짐. **이 구조적 위험 제거는 별도 후속 task**.

**2. `tests/regression/test_replacement_pr_runner_2510.py`** — T17/T18 재구성(과차단 검증 → 정밀 검증)
- git show **실패/returncode non-zero** → fail + 기존 non-empty 파일 보존 검증.
- git show **성공 + 정상 empty blob** → empty file 반영 **허용** 검증(Gemini false-positive 해소).
- Guard 1: target이 repo root 밖 → fail 검증(유지).
- 기존 tmp_path 격리(T01/T03/T04…) **유지**.

## 검증 (필수)
1. `pytest tests/regression/test_replacement_pr_runner_2510.py` 전체 PASS(개수 명시).
2. ★ 위 pytest 실행 **전/후 canonical 2파일 size/sha 불변**(0바이트 미발생) 명시.
3. Gemini HIGH가 지적한 **false positive(정상 empty-file PR 차단)가 해소**됐는지 코드로 설명.
4. diff가 **2파일뿐**(merge_queue_executor·forbidden 무접촉) 확인.

## ★ 명확히 기록 (GPT 필수)
- **A안은 완전한 코드 방어가 아님**: 현재 재현된 QC truncate는 (테스트 tmp_path 격리 + Guard1 + GIT_SHOW_FAILED)로 막지만, **"repo_dir 미지정 시 WORKSPACE fallback" 구조적 위험은 이번 PR에서 완전히 제거되지 않음**. → 후속 task 필요.

## 후속 task 후보 (이번 범위 아님 — 기록만)
`transplant/write 경로 repo_dir mandatory화 or WORKSPACE fallback 제거 + merge_queue_executor.py:1745 호출부 repo_dir 주입 + dormant real-merge 경로 영향 검증`. 별도 expected_files·별도 승인.

## 금지
신규 PR 생성 · merge · merge_queue_executor/real_merge_hooks 접촉 · WORKSPACE fallback mandatory화 · ci.yml/ruleset · thread 임의 resolve.

## 산출물 & 보고
1. 브랜치 `task/task-2783-dev3`에 커밋 + push(PR #262 갱신).
2. ANU 보고: 수정 diff(2파일) / pytest 결과 / canonical size/sha 불변 / Gemini FP 해소 설명 / A안 한계(구조위험 미제거) 명기.
3. 봇 종료 전 ANU callback(envelope만·UTF-8 ≤3900B).

## goal_assertions (auto-generated)
- `pytest tests/regression/test_replacement_pr_runner_2510.py`
