# [InsuRo] Phase 1a — 보장분석 백엔드: 증권 추출 + 정규화 + grouping 연결

## 단일소스 (필독)
- 계획: `/home/jay/workspace/memory/plans/insuro-policy-analysis_260812/plan.md` (Phase 1)
- taxonomy·정독원칙: `/home/jay/workspace/memory/project_insuro_cancer_coverage_taxonomy_260812.md`
- grouping 엔진(완성·main 반영): InsuRo `server/policy_grouping/` (task-2938, origin/main ba63045)

## 목표
설계사가 업로드한 **고객 증권(PDF/JPG)** 에서 담보를 추출→정규화→(task-2938 엔진) grouping 연결하여 **보장분석 표의 데이터 구조**를 생성한다. ⚠️ **표 렌더/프린트/검수 UI(Phase 1b)는 이 태스크 범위 아님**(별도 brainstorming 후).

## ★ 실증권 (골든셋 · PII 주의)
경로: `/home/jay/.cokacdir/workspace/autoset/강연우가족증권/` (강연우 가족: 강혁=父, 이고은=母, 강연우=子)
- `강연우-현대해상 어린이보험.pdf` (8p, **텍스트레이어 PDF**, 담보별 구조화)
- `강혁-메리츠화재 담보내용.pdf` (1p, **텍스트레이어 PDF**, 계약사항+담보)
- `강혁-교보생명 보험증권.pdf` (4p, **이미지 PDF — 텍스트레이어 없음 → vision 필요**)
- `이고은-우체국암보험_01.JPG` `_02.JPG` (**JPG 2장 → vision 필수**)
- 정답 output 양식: `/home/jay/.cokacdir/workspace/autoset/강연우(아들) 가입현황 260115.pdf` (강연우 보장분석 결과 예시)

⚠️ **PII (실명·증권번호·주민번호)**: 증권 원본·추출결과를 **git 커밋 절대 금지**. 로컬 fixture 경로로만 사용, repo에는 마스킹/합성 샘플만.

## 추출 대상 필드 (증권 실측 구조)
담보별: **담보명 · 가입금액(만원) · 보장보험료 · 납기/만기 · 보장기간 · 지급조건(사유 텍스트)** + 증권 헤더(보험사·상품명·피보험자·계약일).

## 구현
### 1. 증권 추출 어댑터 (`server/policy_extract/` 신규)
- **텍스트레이어 PDF**: pymupdf 파싱(현대/메리츠 구조). `policy_analyzer` 기존 로직 재사용/래핑 가능하면 재사용(중복 금지).
- **이미지 PDF / JPG vision**: **아누시스템(claude vision, 무학습 P0-2 경로)** 어댑터 신규. 증권 이미지 → 담보 필드 구조화 JSON. (task-2938 `reading.py`의 anu_provider 사용 패턴 참고)
- 형식 자동 판별(텍스트레이어 유무 → 파싱 vs vision).
- 출력: 피보험자별 담보 리스트(위 필드).

### 2. 정규화 (`server/policy_normalizer.py` 신규)
- 추출 담보 → **대구분 매핑**(순서 고정, 변경 금지): 실손 → 진단비 → 치료비 → 수술비 → 일당 → 장애 → 요양 → 사망 → 운전 → 생활.
- 매핑 근거 provenance 보존. 미매핑=미분류 버킷(억지 배정 금지).

### 3. grouping 연결 (task-2938 엔진)
- 암 담보 등은 **task-2938 `server/policy_grouping` 지식DB 룩업**으로 taxonomy 그룹 배정.
- ⚠️ **이름 매칭 grouping 금지** — 지식DB(약관 정독 축적) 경유. cold start(지식DB 빈 상태)=미분류 버킷 or 설계사 질문 큐(엔진 hitl 재사용).

### 4. 데이터 구조 (보장분석 표 소스)
- 피보험자별 + **회사별 열 병합**(같은 담보 합산), 대구분 순서, 셀=가입금액(만원)/없으면 "-".
- **UNKNOWN 정책**: 계산 불가(가입금액 0 등)=UNKNOWN 표기("0원"과 구분). 담보별 보험료 없으면 UNKNOWN(억지배분 금지, 금소법).
- 계산은 **결정적 함수**로 분리(AI 수치환각 금지).

## 검증
- **실증권 5건 골든셋**: 강연우 증권 추출 → `강연우 가입현황` 정답과 대조(담보/금액 일치율). 다른 형식(텍스트PDF/이미지PDF/JPG) 각 1건 이상 추출 성공.
- pytest. 계산 역산 검증.
- ⚠️ 실증권 PII는 fixture 로컬만, 커밋 금지.

## 제약
- 정독/키워드금지 원칙(taxonomy 문서), grouping=엔진 경유, 계산=결정적함수.
- 신규 모듈 분리: `policy_extract` / `policy_normalizer`. `policy_analyzer`=추출 유지(래핑).
- merge_policy: tiered. Phase 1b(UI)는 범위 밖.

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "server/policy_extract/**"
    - "server/policy_normalizer.py"
    - "server/tests/**"
  forbidden_paths:
    - ".env"
    - ".env.*"
    - "server/policy_grouping/**"   # task-2938 엔진은 읽기만, 수정 금지
    - "server/policy_analyzer.py"    # 래핑만, 수정 금지
  commands: ["pytest", "python3 -m py_compile", "python3 -c"]
  merge_policy: "tiered"
  ttl_hours: 48
```

## 완료 보고 (.done + 보고서)
- 추출 어댑터 diff / 정규화·grouping 연결 / 실증권 5건 추출 결과(마스킹) / 강연우 정답 대조 일치율 / UNKNOWN 처리 / PII 커밋 0 확인 / callback envelope(UTF-8 ≤3900 bytes)
