★★★ 작업 취소됨 (CANCELLED) ★★★

# PR103_GEMINI_FIX — qc_report_guard.py Gemini 지적 2건 수정

> **이것만 고치면 PR #103 이 머지 가능해지고, 5월부터 막힌 전체 머지 교착이 풀린다.**

## base / branch
- 저장소 **`/home/jay/projects/InsuRo`**
- **기존 브랜치 `task-2450-multi-repo-enforcement` 에 이어서 커밋** (현재 head `38bea9b`, rebase 완료 상태)
- worktree: 신규 생성 권장. ⚠️ **rebase·force-push 하지 마라**(이미 최신 main 위에 올라가 있다)

## expected_files (정확히 1파일)
```yaml
allowed_resources:
  paths: ["scripts/qc_report_guard.py"]
  new_file_limit: 0
  commands: ["git","python3"]
  merge_policy: "none"
```
⚠️ `.github/workflows/taskctl-ci.yml` **수정 금지**(게이트 정의. 건드리면 required check 가 깨진다).

## 배경
PR #103 은 required check 8종을 **전부 통과**했으나, ruleset 의 **`required_review_thread_resolution = True`** 때문에 **Gemini 리뷰 미해결 2건**이 머지를 막고 있다.

## 수정 요구 — Gemini 지적 그대로

### ① `scripts/qc_report_guard.py:40` — **Path Traversal (security-high)**
현재:
```python
task_id = (args.task_id or "").strip()
```
→ `task_id` 가 `/` 로 시작하거나 `../` 를 포함하면 **`workspace` 를 벗어나 임의 파일 접근**이 가능하다.

**Gemini 제안**:
```python
task_id = os.path.basename((args.task_id or "").strip())
```
- `os.path.basename()` 으로 파일명만 추출하거나, **경로 구분자 포함 여부를 검증**하라.
- ⚠️ `basename` 만으로 충분한지 판단하고(예: 빈 문자열·`.`·`..` 결과), **부족하면 추가 검증**을 넣어라. 근거를 보고에 남길 것.

### ② `scripts/qc_report_guard.py:68` — **UnicodeDecodeError 미포착**
현재:
```python
try:
    body = qc_result.read_text(encoding="utf-8").strip()
except OSError as exc:
```
→ `UnicodeDecodeError` 는 **`OSError` 하위가 아니라** 잡히지 않아 **스크립트가 비정상 종료**된다.

**Gemini 제안**:
```python
body = qc_result.read_text(encoding="utf-8", errors="replace").strip()
```
- 또는 `except (OSError, UnicodeDecodeError)` 로 확장. **둘 중 무엇이 이 스크립트 목적(graceful guard)에 맞는지 판단**하고 근거를 남겨라.

## 검증
- `python3 -m py_compile scripts/qc_report_guard.py` PASS
- **Path Traversal 방어 실증**: `--task-id "../../etc/passwd"` · `--task-id "/etc/passwd"` 같은 입력으로 실행해 **workspace 밖 파일을 읽지 않음**을 보일 것(실행 원문 첨부)
- **UnicodeDecodeError 실증**: 비-UTF8 바이트가 든 `qc-result` 파일을 만들어 실행 → **비정상 종료하지 않고 graceful 처리**됨을 보일 것
- 기존 정상 동작(파일 없으면 skip) **유지** 확인

## ★ 절대 제약
- **PR 생성 0** (PR #103 이 이미 존재한다) · **main merge 0**
- **커밋 정확히 1개**. push 는 `git push origin HEAD:task-2450-multi-repo-enforcement` (force 금지)
- **금지**: `.github/workflows/**` 수정 · rebase · force-push · 기능 추가 · 다른 파일 수정

## 봇 안전 프로토콜
- Edit·commit·push 직전마다 **cancel 마커 재확인**
- **`.done` 자동마커는 완료 증거가 아니다** — ANU 독립검증이 권위. 커밋·보고서 반드시 남길 것

## 보고
- `/home/jay/workspace/memory/reports/pr103-gemini-fix.md` (저장소 밖 · git stage 0)
- diff / 지적 2건 각 조치 근거 / **Path Traversal·UnicodeDecodeError 실증 원문** / MATCH·GAP
- 봇 종료 전 ANU callback(envelope만·UTF-8 ≤3900B, collector=ANU key c119085addb0f8b7)

## goal_assertions (auto-generated)
- `python3 -m py_compile scripts/qc_report_guard.py`
