# 복합설계 계산기 — Phase 0 전축 읽기전용 실사 결과

**작성**: 아누 (2026-07-16 KST) · **대상 SHA**: `10e488ffb44ba88551900dc5fac6d142f5e668da` (main, working tree clean)
**방식**: 4축 병렬 subagent 실사(축1~3) + ANU 직접(축4). **코드/DB/설정 수정 0.** 모든 판정에 증거(file:line).
**원칙**: 파일 존재 ≠ live. 증거 없으면 UNKNOWN.

---

## 축1 — 확장 캡처
- **inject.js = DEAD_CODE**(no-op, `inject.js:1-13`). 옛 자동 push 경로 폐기(회장 결정 #4).
- **content.js DOM 스크래핑 = WIRED_LIVE**: mmlfcp 셀렉터(`#companyInfo`/`#bojang_lists`/`#premium_lists`, `content.js:362-364`) → 버튼 클릭 → `OHMY_MATRIX_CAPTURED` → `POST /api/insuro/ohmy-capture`. 유닛테스트 29/29 PASS.
- **★ "설치했는데 안 됨" 유력 원인 = 캡처가 아니라 JWT 연결**: ohmymanager 캡처 버튼은 InsuRo JWT가 확장에 연결됐을 때만 렌더(`content.js:110,136`). 그 연결 `setInsuroJwt`가 **ack 없이 마커 존재만으로 true 반환**(`extensionBridge.ts:63-68`) → silent fail 가능 → 버튼 미표시. 감지 자체는 정상.
- **버전 sync(task-2447) = WIRED_LIVE**, 견고(manifest 단일 소스 → 서버응답·zip·URL 일치).
- **방식 B 부활 실현가능성 = MEDIUM**: 인프라(WAR 주입·postMessage relay·background push·버전 sync) 구비. 단 ①확장 코드엔 `/api/ProductPremiums` 계약 삭제됨(우리가 collector+실캡처로 확보) ②회장 결정 #4와 충돌 안 하게 **명시 버튼 클릭 유지** 전제.

## 축2 — 데이터 계약 (★ 최대 발견)
- **데이터 경로 2개 분리**:
  - 경로 A(서버 collector, deprecated): `/api/ProductPremiums` → `coverage_premiums[].detailList[].{coverage_cd,premium}` → `ohmy_premiums`. **고객 개념 없음.** ← "옛 코드 스키마 확정"이 이 경로.
  - 경로 B(현재 live 브라우저 캡처): content.js **DOM 스크래핑** → `ohmy_capture_history.matrix`. **`/api/ProductPremiums` 미사용.** 계산·CRM 전부 이 B 스키마에 강결합.
- **→ 방식 B는 "부활"이 아니라 어댑터 필요**: `/api/ProductPremiums`(A스키마) → 현행 matrix(B스키마 `{insurers:[], coverages:[{cd,name,amount,premiums:{}}]}`) 변환.
- **가입금액(amount)**: 경로 B(DOM `guide_coverage_amount`, `content.js:450-452`)에만 존재. 경로 A(API)엔 미파싱·**UNKNOWN** → DOM 하이브리드 유지 필요.
- **★ 현재 캡처는 "체크된 담보만" 필터 안 함**: `.checked` 무시하고 모든 `checkbox[data-cd]` 수집(`content.js:444-453`). 회장 요구 "체크된 것만" **미구현(GAP)**.
- **premium=0 모호성 해소 = NO**: 코드가 `coverage_cd`·`premium` 2필드만 읽고 `premium<=0` 무조건 드롭 → '미선택'과 '미제공' 동일 처리(`collector:279-280`, `main.py:7197-7198`). 가입가능 플래그 유무는 UNKNOWN.
- **coverage_cd 매핑**: 32개(JSON 실측), collector 도크스트링 "33" 불일치, JSON파일(main.py)↔DB테이블(collector) 이원화, seed INSERT 없음 → 최신성 UNKNOWN.

## 축3 — 계산 엔진 (★ 안심 발견)
- **실사용 = 서버 Python** `composite_calculator.py`(`/api/insuro/composite-calculate-from-matrix`). 구 프론트 그리디는 task-2354로 제거.
- **단일 회사**: 선택담보 하나라도 결손(키 부재)인 회사를 후보에서 **완전 제외**(`:53`), test PASS. (올바름)
- **2·3사**: 합집합 전담보 커버 강제(`:86-88`) + 미사용/1만원 미만 배정 회사 조합 폐기(`:96`) + 결정론적 tie-break(`:83,:112`), test PASS.
- **GPT 4대 계산결함 판정**: #3(유효조합)·#4(결정론) = **엔진에 없음(방어됨)**. #1(premium=0 가정)·#2(결손 최저오판) = **엔진은 올바르나** mmlfcp scraper가 빈 premium 속성을 `0`으로 기록(`content.js:493,496`) → 결손을 "무료 담보"로 오인시킬 **데이터층 잔여 리스크**(실 DOM 렌더 = UNKNOWN).
- **알고리즘 버전 스탬프 = 없음**(GAP). **20년 총액 = 갱신형 미구분 평탄곱**(`MaturityCompare.tsx:395`, 결함).
- 테스트 17 passed.

## 축4 — CRM / 히스토리
- **Ingest = WIRED_LIVE**(`main.py:7305~`): 기존 매칭 → `match_candidate`(customer_id 자동갱신 안 함, **confirm 대기 — 안전**). **무매칭 → `upsert_customer_for_capture` 자동 신규등록**(tags `temporary/auto_ohmy`, `customer_match.py:57-79`) — **★ 홍길동 위험, 변경 필요.**
- **★ 저장 계층 GAP**: `ohmy_capture_history`는 **캡처 원본만**(matrix+메타+암호화PII, `011:3-19`). **분석 스냅샷(+algo_version)·상담 기록·재분석·상태(draft/superseded) 컬럼 전무** → GPT 4계층 대비 3계층 부재(SCHEMA_GAP).
- **CRM 조회/링크/재배정 UI = WIRED**: `CustomerMatchDialog`/`HistoryReassignDialog` + CrmCustomers ohmy-history. vitest 존재.
- **PII 암호화**(`pii_crypto.py`) WIRED. 마이그레이션 011 + customers pii = 파일 존재, **prod 적용 여부 UNKNOWN**(DB 접근 없음).

---

## v2 대비 MATCH / GAP / UNKNOWN

**MATCH (재사용 가능)**:
- 계산 엔진(결손처리·유효조합·결정론) — 견고, 재사용.
- CRM 조회/링크/재배정 UI + 기존매칭 confirm 분기.
- 확장 버튼→POST 파이프라인 + 버전 sync(task-2447).
- PII 암호화 모듈.

**GAP (신규/변경 필요)**:
1. 방식 B 어댑터(`/api/ProductPremiums` → matrix).
2. "체크된 담보만" 필터(현재 `.checked` 미필터).
3. premium=0 '미선택 vs 미제공' 구분.
4. 저장 3계층 추가(분석 스냅샷+algo_version 불변 / 상담기록 사용자확정 / 재분석 신버전) + 상태모델(draft/superseded).
5. 무매칭 자동 신규등록 → **확인 후 등록**으로 변경.
6. 알고리즘 버전 스탬프.
7. 20년 총액 갱신형 구분.
8. JWT 연결 ack(“안 됨” 원인 후보).

**UNKNOWN (실증 필요)**:
- `/api/ProductPremiums` 실제 응답에 가입금액·가입가능 플래그 존재 여부 → **회장님 실환경 raw response 1건**으로 해소.
- 결손 담보를 mmlfcp DOM이 0으로 렌더하는지 빈 셀인지.
- 마이그레이션 prod 적용 여부.
- coverage_cd 매핑 최신성(JSON 32 ↔ DB 테이블).

---

## 종합 의미 (v2.1 방향)
1. **방식 B = "부활"이 아니라 "어댑터 + DOM 하이브리드"**: 보험료는 API 가로채기, 체크상태·가입금액·고객정보는 DOM. 어댑터로 현행 matrix 스키마에 맞춤.
2. **계산 엔진은 튼튼 → 재사용.** 리스크는 데이터층(캡처 정확성)에 집중 → Phase 1(캡처 정확성)이 최우선.
3. **CRM 파이프라인 재사용하되 저장 3계층 확장 + 자동 신규등록 confirm화** 필요.
4. UNKNOWN 대부분은 **회장님 실환경 캡처 1건(raw response)**으로 해소 → Phase 1의 필수 입력.
