# [Lv.4] scope-guard stale-base 오탐 근절 (SCOPEGUARD_STALEBASE_FIX)

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "scripts/finish-task.sh"
    - "scripts/worktree_manager.py"
    - "scripts/task-scope-guard.sh"
    - "tests/**"
    - "memory/reports/**"
  forbidden_paths:
    - "memory/events/task-2814.*"
    - "/home/jay/projects/InsuRo/**"
    - "server/**"
    - "src/**"
    - ".github/**"
  commands:
    - "pytest"
    - "bash"
    - "python3 -m py_compile"
    - "git"
  merge_policy: "tiered"
  ttl_hours: 24
```

## ★ 착수 전 필독 (근거·설계)
- 설계 3문서: `memory/plans/scope-guard-stale-base-fix/{plan_260721.md, context_260721.md, checklist_260721.md}` **전부 읽어라.**
- **재현 증적(먼저 읽어라 — 이후 이 파일들은 rename 될 수 있으니 착수 시 즉시 복사/기록)**:
  - `memory/events/task-2814.scope-violation.json` (12건 오탐 원본)
  - `memory/events/task-2814.followup.txt`, `memory/reports/task-2814.md` §266-320 (dev6 페룬이 이미 근본원인·부수버그 규명해둠)
- **본 버그를 어제 처음 맞은 게 dev6(당신 팀)이다.** task-2814.md §280-308 의 자체 진단을 신뢰 기반으로 활용하라.

## 문제 (한 줄)
finish-task scope-guard 가 diff base 를 stale 하게 잡아, 이어받기(branch-continuation) task 에서 **이전 커밋 유래 변경을 현재 task 의 범위위반으로 오탐** → SCOPE_GUARD_FAIL → 정상 완료/콜백 차단. (실증: task-2814 12건, task-2815 24건 — 모두 자기 커밋은 범위 내였음)

## 근본원인 (실측, 코드 라인)
- `scripts/finish-task.sh:840-870`:
  - 비-STRICT: `git diff main..HEAD` (로컬 `main`, stale) → 폴백 `HEAD~1` (다중커밋 task 오측)
  - STRICT: `merge-base(origin/main, HEAD)` — **fetch 선행 없음**, `worktree-base.json` 폴백은 merge-base 성공 시 무시(`:843-846`)
- `scripts/worktree_manager.py:306-590`: base_sha 캡처가 **재사용/rebase 브랜치 미커버** → `base_sha: null` 또는 rebase 이전 부모 아닌 현재 origin/main 기록. **이게 상류 방아쇠.**

## 요구 구현 (fail-CLOSED 유지가 최상위 제약)
1. **캡처 정확화** (`worktree_manager.py`): dispatch/worktree 생성 시 **HEAD 의 실제 조상인 base_sha 를 신뢰 캡처**. 재사용·rebase·stacked 케이스 커버. `base_sha: null` 기록 금지. **캡처 실패는 dispatch 시점에 fail-closed**(네트워크 있는 시점에서 실패를 노출 — finish 시점 오프라인 봇 DoS 회피).
2. **소비측 가드** (`finish-task.sh`): scope base 우선순위 = `worktree-base.json`(1순위, 이제 신뢰) → 없으면 `git fetch origin <main>` 후 merge-base(2순위) → 그래도 없으면 **fail-closed exit 1**. **stale 로컬 ref 로의 조용한 폴백 제거.**
3. **ancestor 가드** (`finish-task.sh`): diff 전에 `git merge-base --is-ancestor "$SCOPE_BASE" HEAD` 확인. 조상 아니면 fail-closed (엉뚱한 트리 비교 차단 — Codex 지적).
4. 비-STRICT 경로의 로컬 `main..HEAD`/`HEAD~1` 폴백을 위 로직으로 **통일**.

## 검증 (양방향 필수 — 하나라도 실패 시 미완료)
- **오탐0**: stale 로컬 main + 브랜치에 무관 머지이력 재현(task-2814/2815 시나리오) → 위반 **0**
- **진짜위반 검출**: 확장 task 가 server/** 수정 → **여전히 차단**
- **fail-closed**: base 미확정/ non-ancestor → **exit 1**, 조용한 스킵(fail-open) 없음
- 기존 finish-task 회귀 테스트 전부 green

## ★ self-completion 주의 (Codex 지적 — 반드시 반영)
이 task 자신도 finish-task.sh 로 완료한다. `worktree_manager.py finish` 실패가 삼켜져 `.merge-done` 오기록되는 경로(`finish-task.sh:1020-1025`)가 있으니:
- 본 task 는 **`FINISH_TASK_WORKTREE_STRICT=1` + 정확한 worktree-base + worktree cwd 에서 finish** 실행.
- 만약 자기 완료가 scope-guard 로 또 막히면 **`.done` 수동생성·allowed_resources 변조·`.allow-no-scope` 우회 전부 금지**, task-2814 처럼 **result.json + ANU callback 으로 escalate** 하라(아누가 수동 종결).

## 부수버그 2건 — **본 task 범위 밖. 수정 금지. 보고서에 재확인만.**
dev6 가 task-2814 에서 발견(참고용, 별도 백로그):
- `teams/shared/verifiers/browser_verify.py:14` workspace 루트 `..` 4단계(정답 3단계)
- `finish-task.sh` QC evidence root: `project_path` 생략 시 `$WORKSPACE` 폴백(`:734`)

## 금지
- fail-open(빈 diff 스킵) 도입 금지 · 검증 완화 금지
- InsuRo repo/server/**/src/** 변경 금지
- `memory/events/task-2814.*` 마커 rename/삭제 금지 (아누가 T1 에서 처리)
- 자동 fire/코드훅 강제 추가 금지

## 완료
- `scripts/` + `tests/` 외 변경 0 (`git diff --stat` 증명) → PR → Gemini 리뷰 → High 0
- 결과 `memory/reports/` 기록 + **ANU callback** (UTF-8 ≤3900 bytes, envelope 만)