# task-2957 · InsuRo 증권분석 Phase 1b — 보장분석 대구분 표 (codex↔ANU 합의)

## 배경
- 증권분석 본류 복귀. Phase 1a(백엔드: policy_extract/policy_normalizer/grouping) 머지됨(task-2943, PR#209). **Phase 1b(보장분석 표 UI) 미착수.**
- **codex↔ANU 합의 핵심**: 다중 증권 병합 표 생성 함수 `build_analysis_table()`가 **이미 구현됨**(`server/policy_normalizer.py:232`,`:377` — columns/sections/rows/cells/total/recommended_total, 같은 담보 합산·없으면 "-"·불명 UNKNOWN). 표를 새로 만들지 말고 **재사용**한다.
- **갭**: 현재 `analyze-policy`(`server/main.py:6998~7041`)는 Phase 1a 파이프라인을 안 쓰고 옛 AI 결과(`meta+coverages`, `policy_analyzer.py`)만 반환. 프론트 `PolicyAnalysis.tsx`는 개별 카드+단순 합산(카테고리 리스트+막대)이라 "표"가 아님.
- repo `/home/jay/projects/InsuRo`, origin/main `6eeb5b6`. 용도=보장분석(고객 공개 양식). 담당 dev2.

## ★ 확정 설계 (codex↔ANU 합의 — 임의 변경 금지)
### 백엔드
- `analyze-policy` job 내부에서 `policy_extract`(PDF→CoverageRecord) → `policy_normalizer.build_analysis_table()` 호출 → 결과를 job/result에 **`analysis_table` 병행 필드로 추가**. **기존 `meta+coverages`는 유지**(하위호환). 저장·상태조회 응답에 전파.
- 회사별 열 헤더 메타(가입연월·납입기한/만기·보험료·납입잔여개월)는 `PolicyColumn`으로 계산.
- 금소법: `build_analysis_table`은 결정적 함수 — 그대로 재사용. 값 없으면 "-", 계산불가 UNKNOWN(억지배분 금지). AI 추측으로 표 채우기 금지.

### 프론트
- `PolicyAnalysis.tsx`의 **`aggregated` 탭**(현재 `aggregatedCoverages` 계산부+렌더부, `:343`·`:559`·`:694`)을 **`analysis_table` 소비형 대구분 표로 교체**. 개별 증권 카드 탭은 그대로 유지.
- 표: 대구분 순서 고정(실손→진단비→치료비→수술비→일당→장애→요양→사망→운전→생활, 미분류 끝) · 열=담보 | 권장가입금액 합계 | 회사별(상품명·가입연월·납기/만기·보험료·잔여개월) · 셀=가입금액(만원) 없으면 "-", 불명 UNKNOWN.

### 범위 밖 (후속)
- print/PDF(window.print+print CSS)·설계사 grouping 검수 워크플로우(status/reason/question)는 **이번 제외**(데이터 계약 먼저, 재작업 방지).

## 리스크
- policy_extract 실증권 recall 한계(task-2943 P0 73.9%·실손담보 부재 갭) → 미분류 버킷·UNKNOWN 정직 표기. 정확도 과장 금지.
- analysis_table과 기존 coverages 이중 소스 → analysis_table을 표의 단일 진실로, coverages는 개별 카드용으로 역할 분리 명시.

## 완료 조건
- **PR**(백엔드+프론트) + 회귀 + `npm run build` PASS + **실브라우저 스크린샷**(aggregated 탭 대구분 표).
- `memory/reports/task-2957.md` + `.done` + ANU 콜백(≤3900B).
- **머지·배포 HOLD** — ANU 검증 + 회장 보고 후. Surgical(기존 analyze-policy·개별카드 무변경, 병행 추가).
