# task-2757+2 — v2.13 gate forbidden/expected matching 구조 재설계 (B-1) 결과

- 상태: PR236_TO_R3_MATCHING_STRUCTURAL_REDESIGN_APPROVED_ACTIVE_FALSE (ACTIVE=false)
- base: clean origin/main 8420a763 / 참조: origin/task/task-2757+1 (8e831279) 7파일
- branch: task/task-2757+2 (push only, PR 0 — ANU가 fresh PR 생성)
- head: 5c6000605c10c70d9f2b91a53fd645551ffea257
- 테스트: 138 passed (기존 122 유지 + R3 16 추가)

## 핵심 (substring `in` 매칭 전면 제거)
dispatch/v2_13_gate.py 내부 헬퍼 분리(새 파일 0):
- `normalize_path()` — leading `./`·`a/`·`b/` 제거, 중복 slash 축약, OS sep→posix, 경로 소문자화 금지(대소문자 보존), 컴포넌트 단위.
- `_extract_touched_files()` — diff `+++ b/<path>`/`--- a/<path>` 헤더 및 tool_calls file path 필드에서 touched_files 정확 추출.
- `_glob_match()` — 경로 컴포넌트 단위 glob(`**`=0+ 세그먼트, `*`/`?`=세그먼트 fnmatchcase, 대소문자 구분).
- `_match_forbidden_paths()` — forbidden 글롭 ↔ touched_files 컴포넌트 매칭.
- `_match_forbidden_ops()` — forbidden op word-boundary(`\b`) exact 토큰/구문 매칭(공백 `\s+` 흡수).
- `detect_allowlist_axis` — forbidden_path 축을 위 헬퍼로 분리(둘 중 하나 적중 시 활성).
- expected_files 비교 → `normalize_path()` set membership (MED L472).
- `_flatten_tool_calls` dead if/else 제거 (MED L137).

## Medium 동반 처리
- dispatch/control_db_guard.py: `_is_sqlite_write` redundant `.lower()` 제거 (MED L32, haystack는 호출부에서 이미 소문자화).
- scripts/correction_budget.py / scripts/migrate_capability_matrix_v213.py: `git rev-parse --show-toplevel` 서브프로세스 결과를 module-level 1회 캐시(perf x2). ANU_WORKSPACE/cwd는 매 호출 평가하여 테스트 monkeypatch 격리 보존.

## 필수 테스트 (모두 통과)
- forbidden `rm` ↛ `form`/`warmup`, 단독 `rm` 토큰은 매칭.
- forbidden path `api` ↛ `capital`/`rapid`.
- `./`·`a/`·`b/`·무접두 경로 동일 취급.
- glob `**/*.service` 매칭(하위/최상위 모두).
- `dispatch/x` ↛ `dispatch/xyz.py` (컴포넌트 경계).
- tool_calls file path → touched_files 추출 매칭.
- expected_files normalize set membership (inside/outside).
- 기존 122 회귀 유지.

## 수정 범위 = 7파일 내부만 (scope 위반 0, 새 파일/모듈 0)
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

## 금지사항 준수
merge/admin override/ACTIVE=true/systemd/callback·wake launch/event strategy/external probe/7파일 밖 수정/새 파일/substring `in` 잔존/PR 생성 — 전부 미수행. branch push only.
