# [Lv.2 surgical] 소식지 교차검증 — OpenAI API → **codex cc(codex CLI)** 로 교체

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "server/newsletter_cross_verify.py"
    - "server/tests/test_newsletter_cross_verify.py"
  forbidden_paths:
    - ".github/**"
    - "extension/**"
    - "src/**"
    - "server/migrations/**"
    - "server/main.py"
    - "server/newsletter_review.py"
    - "server/newsletter_validation.py"
  commands: ["pytest","python3","git"]
  merge_policy: "none"
  ttl_hours: 10
```
> ★ base=현 origin/main(84b3d0b). **회장 지시(260805): 교차검증 2차 엔진을 OpenAI API 가 아니라 우리 시스템의 codex cc(codex CLI)로.** 이유: 새 API 키 불필요 + 외부 API 신규 연동/데이터 egress 우려 회피(내부 도구 사용). 로직·플래그 스키마·파이프라인 배선·검증 초점(숫자 오인식+의미 왜곡)은 **전부 그대로**, **호출 메커니즘만 교체**.

## 배경 (수술 범위)
`server/newsletter_cross_verify.py` 는 현재 `_call_openai_chat_completions`(httpx → api.openai.com, gpt-4o, OPENAI_API_KEY)로 2차 검증. 이미 **주입 이음새 `openai_call_fn: Optional[Callable]`** 가 있어 호출부만 갈아끼우면 됨.

## 작업 (surgical)
1. **`_call_codex_cli` 신규**(async): `codex exec` 비대화식 서브프로세스로 프롬프트 실행 → raw 문자열(JSON) 반환.
   - 호출 형태: `codex exec --approval never -m <model?> ` + **프롬프트는 stdin 으로 주입**(codex exec 는 인자 없으면 stdin 에서 instructions 읽음). 샌드박스=읽기전용/실행금지(모델이 쉘 실행 시도 못 하게), `--approval never`.
   - ★ **오버헤드/컨텍스트 오염 방지**(InfoKeyword claude CLI 교훈): **clean cwd(예: /tmp)** 에서 실행해 프로젝트 CLAUDE.md/무거운 설정 로딩 회피. timeout(예: 60s). codex 가 설정/MCP 로딩으로 느리면 최소 config 로.
   - stdout 에서 JSON 블록만 파싱(코드펜스/잡텍스트 섞이면 관대하게 추출).
2. **기존 OpenAI 경로 제거/대체**: `_call_openai_chat_completions`·httpx·`_OPENAI_CHAT_COMPLETIONS_URL`·OPENAI_API_KEY 의존 제거. 주입 이음새는 유지하되 **기본 구현 = `_call_codex_cli`**(테스트 주입성 보존). `DEFAULT_MODEL` 은 codex 용으로 조정하거나 codex 기본 사용.
3. **플래그 `detail.verifier` 값**: `"gpt-4o"` → `"codex"`.
4. graceful 유지: codex CLI 미설치(PATH 없음)/비정상 종료/타임아웃/JSON 파싱 실패 → 파이프라인 중단 없이 `cross_model_unavailable` INFO 1건.

## 불변 (건드리지 말 것)
- 플래그 스키마(`number_misread`/`meaning_drift`/`cross_model_unavailable`), extractive-only·플래그only, run_review_pipeline 배선(newsletter_review.py), 검증 초점(숫자·의미; insurer·date 제외). newsletter_review.py·main.py·validation.py·migration·src 불변.

## 검증
- `pytest server/tests/test_newsletter_cross_verify.py` — **codex CLI subprocess 를 mock**(httpx mock 제거)으로 기존 16 케이스 동등 통과: 숫자오류→number_misread HIGH / 원문없는주장→meaning_drift HIGH / 정확→[] / codex 미가용·예외·파싱실패→cross_model_unavailable / body 불변 / insurer·date 미생성. 전체 `pytest server/tests/` 회귀 0.
- ★ **L1 실호출 1회**(선택이지만 권장): clean cwd 에서 `codex exec` 가 짧은 프롬프트에 JSON 으로 초 단위 응답하는지 실측(claude CLI 교훈처럼 무거우면 config 최소화). 결과 보고서에 기록.

## 완료 (★ 순서 B)
- server/ 2파일만. **dev6 금지** — dev1(헤르메스, cross_verify 원저자). 커밋 → push → **★ push 확인** → finish-task foreground 1회 → .done. ANU 독립검증·머지·Codex 사전리뷰·배포는 ANU.

## goal_assertions (auto-generated)
- `pytest server/tests/test_newsletter_cross_verify.py`
- `pytest server/tests/`
