# CI-4B — keyword_pool red 4건 정상화 (정책 공백은 미해결로 남긴다)

> **CI-unblock 의 마지막 조각.** 이것만 되면 main 이 green 이 되어 다른 머지가 풀린다.

## base / branch
- **신규 브랜치** `task/<ALLOCATED_TASK_ID>-ci4b-<TEAM>` 을 **`cc7476bfbd9f6b3ae3c99f9a7136cc9f94cd3ada`** 에서 분기
- worktree 신규 생성
- ⚠️ **`task/ci-4-260719`(`ded17c1`) 를 cherry-pick 하지 마라.** 그 초안은 회장이 **제외 지시**했다. **참조만.**

## expected_files (정확히 1파일)
```yaml
allowed_resources:
  paths: ["server/tests/test_keyword_pool_refresh.py"]
  new_file_limit: 0
  commands: ["git","python3","pytest"]
  merge_policy: "none"
```
⚠️ **`server/scripts/keyword_pool_refresh.py` 수정 절대 금지.** 회장 결정으로 **소스는 유지**한다.

## 목적 (딱 3가지)
1. **red 4건 정상화**
2. **보험 도메인 허용 계약 유지**
3. **일반 noise 차단 유지**

## ★ 주장하지 않을 것
**"정책 공백 해결 완료" 를 주장하지 않는다.** `"보험"` 문자열이 blocklist 전체를 우회하는 문제는 **미해결**이며 **CI-4c(백로그)** 소관이다. 문서·주석에서 해결된 것처럼 서술하지 마라.

## 현재 실패 4건 (`git show cc7476b:server/tests/test_keyword_pool_refresh.py`)
```
test_blocks_recruitment_keyword : is_blocked("보험 채용") is True   ← 실제 False
test_blocks_exam_keyword        : is_blocked("보험 시험") is True   ← 실제 False
test_blocks_fraud_keyword       : is_blocked("보험 사기") is True   ← 실제 False
test_blocks_loan_keyword        : is_blocked("대출 보험") is True   ← 실제 False
```
**회장 2026-07-19 결정**: `"보험"` 포함 면제는 **의도된 보험 도메인 정책**. 위 4개는 **정당한 보험 주제**이므로 통과가 맞다. **소스가 옳고 테스트가 낡았다.**

## 수정 요구

### 1. red 4건 → **보험 문맥 없는 키워드로 교체**
각 패턴을 **여전히 검증하되** 보험 문맥을 뺀다. ANU 실측으로 차단 확인된 후보:
| 패턴 | 교체 키워드 | 실측 |
|---|---|---|
| `채용\|연봉\|시험` | `채용 공고` · `공무원 시험` | True 확인 |
| **`사기\|먹튀\|고소`** | **`전세 사기`**(또는 `투자 사기`) — ★ **반드시 `사기` 계열 유지**(Codex 지적: 카테고리 이탈 금지). 보조로 `먹튀 사이트`·`고소 방법` | 전부 True 확인 |
| `대출\|카드\|주식` | `대출 금리 비교` | True 확인 |

### 2. 경계 테스트 **보존** (`ded17c1` 에서 가져오되 직접 재검증)
면제가 **오타·공백·영문 표기로는 발동하지 않음**을 지키는 계약. 가치 있다.
```
is_blocked("보협 마약")     is True     ← "보험" 오타
is_blocked("보 험 마약")    is True     ← 공백 삽입
is_blocked("insurance 마약") is True    ← 영문 표기
is_blocked("마약 단속")     is True     ← 보험 문맥 없음
is_blocked("살인 사건")     is True     ← 보험 문맥 없음
```

### 3. ★ **제거** — 결함을 정상 정책으로 박제한 것
```
is_blocked("보험 마약") is False    ← 제거
is_blocked("보험 살인") is False    ← 제거
```
및 **"버그가 아니라 현행 정책의 특성화"** 취지의 docstring **제거**.
→ 미해결 공백은 **CI-4c 를 가리키는 주석 한 줄**만 남긴다.

### 4. 보험 도메인 허용 계약 유지
`보험 채용`·`보험 시험` 등이 **통과(False)** 임을 확인하는 테스트는 유지·정리.

## 완료 판정
- `python3 -m pytest server/tests/test_keyword_pool_refresh.py -q -p no:randomly` → **0 failed**
- 보존 5건이 **실제 assert 로 존재**
- 제거 2건이 **존재하지 않음**
- 사기 카테고리가 **`사기` 계열 키워드로 검증됨**
- 테스트 개수 **감소 0** · skip/xfail 증가 **0**
- ⚠️ 소스 파일 **수정 0**

## ★ 절대 제약
- **PR 생성 0 · main merge 0.** 커밋 **정확히 1개**
- **금지**: skip · xfail · assertion 완화 · 소스 수정 · `ded17c1` cherry-pick · 다른 로컬 절대경로

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

## 보고
- `/home/jay/workspace/memory/reports/ci-4b-replacement.md` (저장소 밖 · git stage 0)
- diff / 보존5·제거2·교체4 각 근거 / **pytest 실행 원문** / 테스트 카운트 전후 / MATCH·GAP
- 봇 종료 전 ANU callback(envelope만·UTF-8 ≤3900B, collector=ANU key c119085addb0f8b7)
