# [Lv.3] 소식지 검토 Workflow Phase 2 — 자동검증 9규칙 + AI 1차 자기검증 + grounding (T3+T3b+T4)

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "server/main.py"
    - "server/ai_queue.py"
    - "server/newsletter_review.py"
    - "server/newsletter_validation.py"
    - "server/routes/**"
    - "server/tests/**"
  forbidden_paths:
    - ".github/**"
    - "extension/**"
    - "src/**"
    - "server/migrations/**"
  commands: ["pytest","python3","git"]
  merge_policy: "none"
  ttl_hours: 20
```
> ★ base=현 origin/main(Phase 1 머지됨: migration 017 + newsletter_review.transition_review_status). **Phase 2 = 백엔드 자동검증·AI 자기검증·grounding**. 검토 UI는 Phase 3(별도). 3문서·근거: `memory/plans/newsletter-review-workflow_260805/`.

## 배경 (Phase 1 완료 위)
Phase 1로 상태기계(fail-closed)+감사 스키마 완성. Phase 2 = AI 추출 직후 **자동검증(결정론 플래그) + AI 1차 자기검증(회장 승인) + grounding 저장**을 넣어 검토대기로 라우팅. **소식지 저장 테이블=`newsletters`(PK UUID), review_status는 기존 status와 별개.**

## T3 — 자동검증 워커 (결정론 9규칙, 플래그만)
- `server/newsletter_validation.py` 신규(순수 함수): 추출 결과+원문으로 아래 검출 → `validation_flags` jsonb(레벨 HIGH/MED/INFO). **교정 금지, 플래그만.** 임계 **config 상수**.
  1. 보험사명 화이트리스트 미매칭(HIGH) 2. 숫자 원문 set-diff(추출⊄원문=환각 HIGH / 원문핵심⊄추출=누락 MED) 3. batch bleed(다른 origin 혼입 HIGH) 4. 잘림(종결형 아님 MED) 5. 표붕괴 6. 준법문구 정규식 혼입 7. 중복(제목/해시 INFO) 8. 언어깨짐 9. 날짜 대조.
- **ai_queue 워커 추출 직후 동기 호출** → 결과로 `transition_review_status`를 `extracted→auto_validated→(flag 有)pending_review` 라우팅. ★ **AI 업로드 경로가 review_status='uploaded' 명시 삽입**(context-notes fail-OPEN 방지).
- 추출 하드실패(공백/한글율0/파싱예외) 시 **다른 mode 1회 자동 재추출**(markitdown→vision→vision+ocr, retry_count<2).

## T3b — ★ AI 1차 자기검증 패스 (회장 260805 승인)
- 추출 직후, AI가 **원문 대조**로 필드별 오류를 판정: verdict + **원문 인용 span 강제**(인용 못하면 fail) + 교정 **제안**(적용 아님).
- ★ **숫자·보험사명·날짜는 플래그/제안만, AI 자동수정 절대 금지**(상관오류·자기 환각 보증 위험). 결과=`field_confidence`(내부)·`validation_flags`에 반영(비대칭: 의심만 추가, scrutiny 하향 금지).
- **AI는 발행 승인 권한 0** — pending_review로만 보냄. (LLM 호출 실패/타임아웃 시 graceful: 플래그 "AI검증 미완"로 pending_review, 파이프라인 중단 금지.)

## T4 — grounding 저장
- 필드별 원문 근거를 `{type:'bbox'|'page'|'span', page, offset, quote}` 구조로 저장(bbox best-effort→page fallback). 고위험 필드는 최소 page fallback 필수. field_confidence 내부저장(UI 미노출).

## 제약
- 서버만. migration(017) 불변(추가 컬럼 없이 기존 스키마 사용). 기존 소식지 status/발행 로직·기존 업로드 API 회귀 0. "절감" 무관. 숫자·고유명사 extractive-only.

## 검증
- `pytest server/tests/` 회귀 0. 신규: 9규칙 각 정상/환각/누락/경계 픽스처 / **AI 자기검증이 숫자·보험사명·날짜를 자동수정 안 함**(플래그만) 검증 / AI 검증 실패 시 graceful pending_review / 라우팅(flag→pending_review) / AI 업로드 review_status='uploaded' 명시 / grounding fallback 구조.

## 완료 (★ 순서 B)
- 변경 = server/ 만(migration 제외). src/·extension·.github 불변.
- **dev6 금지** — dev1. 커밋 → push → **★ push 반드시 확인**(Phase1서 push 누락 사고) → finish-task foreground 1회 → .done. background wait 금지. ANU 검증·머지·Phase 3(검토 UI) 위임은 ANU.

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