# task-2757+3 — r4 matching 설계 명세 정정 (matching 축 마지막 correction)

## ★ 회장 결정 (r4 1회 승인 — 2026-06-17, matching 축 마지막)
PR #237 CRITICAL 5 근본 원인 = **r3 명세의 "a/·b/ 무조건 제거" 지시 결함**(dev2 잘못 아님, ANU 명세 오류). r4 설계 정정 1회 승인. **이번이 matching 축 마지막 correction**. 상태 `PR237_TO_R4_MATCHING_SPEC_CORRECTION_APPROVED_ACTIVE_FALSE`. ACTIVE=false.

## base / branch / PR
- base = clean origin/main `8420a763`. **fresh r4 branch `task/task-2757+3`**. 참조 = `origin/task/task-2757+2`(5c600060) 7파일.
- **PR #237 추가 push 금지**. branch push only(ANU가 fresh PR 생성·#237 close 통제). isolated worktree 진행.

## ★ 핵심 정정 (r3 명세 결함 교정)
### 1. normalize_path() — a/·b/ 무조건 제거 금지 (CRITICAL 근본)
- `normalize_path()`는 **일반 경로 정규화만**: `./` 제거 · 중복 slash 축약 · OS separator → posix(`/`). **`a/`·`b/` 접두사 제거 절대 금지** — 실제 repo 경로가 `a/...`·`b/...`일 수 있으므로 보존.
- 소문자화 금지(경로 의미 보존).

### 2. git diff prefix 제거는 diff 헤더 파싱에서만
- `_extract_touched_files`(diff 헤더 파서)에서 **오직 `--- a/<path>` / `+++ b/<path>` 두 형식**에서만 `a/`·`b/`를 diff prefix로 해석·제거.
- 그 외(코드 본문·문자열·일반 경로)에선 `a/`·`b/` 보존.

### 3. touched_files 출처 구분
- forbidden path 비교 시 **diff 헤더 추출 touched_files**(diff prefix 제거됨)와 **tool_calls file path**(실제 경로, prefix 제거 안 함)를 **구분해 정규화**. tool_calls의 `a/secret.py`는 실제 경로로 보존.

### 4. forbidden operation 경계 — \b 한계 보완
- `\b`만 쓰지 말 것(비단어 문자로 시작/끝나는 op 누락). **명시적 경계 함수**:
  - 단어형 op → token boundary 매칭
  - 구문형 op → shlex 또는 whitespace-normalized **exact phrase** 매칭
- substring `in` 매칭 **재도입 금지**.

## Medium 파생
같은 matching/spec 축이면 함께 닫음(테스트 경로 현실화·주석 정정·redundant lower/CHAIR_ACTORS set 재생성). 별도 축이면 보류 보고.

## 필수 테스트 (각각)
- 실제 경로 `a/secret.py`가 `secret.py`로 **깎이지 않음**
- diff 헤더 `+++ b/secret.py` → `secret.py` 추출됨
- diff 헤더 `--- a/secret.py` → `secret.py` 추출됨
- tool_calls file path `a/secret.py`는 **실제 경로 보존**
- forbidden path `a/secret.py`가 실제 `a/secret.py`에 **매칭됨**
- forbidden path `secret.py`가 실제 `a/secret.py`에 **오매칭 안 됨**
- 비단어 문자 포함 forbidden op가 `\b` 한계로 **누락 안 됨**
- 기존 138 테스트 유지

## 수정 범위 = 7파일 내부만
dispatch/v2_13_gate.py · dispatch/control_db_guard.py · scripts/correction_budget.py · scripts/promotion_guard.py · scripts/migrate_capability_matrix_v213.py · memory/schemas/goal_contract_schema.json · tests/regression/test_v213_phase1_gate_2757.py

## 금지 (위반 시 STOP_REPORT)
merge · admin override · ACTIVE=true · systemd · callback/wake · C(event strategy) · external probe/ANU-Control daemon 확장 · 7파일 밖 수정 · **새 파일/새 모듈** · **substring `in` 재도입** · **normalize_path의 a/·b/ 무조건 제거** · PR 생성/push to main.

## 중단 조건 (STOP_REPORT)
7파일 밖 수정 필요 · 새 파일 필요 · matching 축 HIGH/CRITICAL 재발 · credential/permission/systemd/production/callback/wake/merge 축 터치 · 7파일 내부로 안 닫힘. (★ r4 후 matching 축 HIGH/CRITICAL 재발 시 = 미세수정/동일 PR 계열 수렴 중단, PR 폐기 후 별도 설계 리뷰 전환 — 회장 결정 사항이므로 즉시 STOP_REPORT.)

## 산출물 / callback
`task/task-2757+3` branch commit + push(PR 0). 종료 전 ANU normal callback 필수 — ANU key `c119085addb0f8b7`(self-key 금지·UTF-8 wc -c ≤3900 bytes·envelope만: task_id/branch/head/result_path/sha256/collector_role=ANU/one-line).

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "dispatch/v2_13_gate.py"
    - "dispatch/control_db_guard.py"
    - "scripts/correction_budget.py"
    - "scripts/promotion_guard.py"
    - "scripts/migrate_capability_matrix_v213.py"
    - "memory/schemas/goal_contract_schema.json"
    - "tests/regression/test_v213_phase1_gate_2757.py"
  forbidden_paths: ["**/*.service","**/*.path","dispatch/anu_pickup_driver.py","dispatch/anu_result_pickup_runner.py",".github/**"]
  commands: ["pytest","python3 -m py_compile","git"]
  merge_policy: "none"
  ttl_hours: 12
```
