# task-2882 보고서 — 생보 감지 수정(옵션 텍스트 "생보" 우선 판정 + 메시지 문구)

## 메타
- 작업 ID: task-2882
- 팀: dev2 (오딘) / 구현: 프레이야(프론트엔드, sonnet)
- 레벨: Lv.2 · merge_policy: **none** (머지는 ANU)
- 프로젝트: InsuRo (`/home/jay/projects/InsuRo`)
- worktree: `/home/jay/projects/InsuRo/.worktrees/task-2882-dev2` · 브랜치 `task/task-2882-dev2`
- base: origin/main `ed76645` (#156 Phase B 포함) · 커밋 `d18c75c` (push 완료)

## SCQA

### Situation
생보 3대질병 Phase A/B 머지 후, 회장 실사용에서 "생보 이어서 캡처" 클릭 시 오판정 발생.

### Complication
`content.js`의 `isSelInsuranceTypeLife()`가 `#selInsuranceType.value === "LF"` **값코드 하드코딩**으로만 생보를 판정. 오마이매니저에서 생보 선택 시 실제 value가 "LF"가 아닐 수 있어(UNVERIFIED) 생보인데도 "화면을 생손보(LF)로 전환한 뒤 다시 시도" 라는 잘못된 안내가 노출됨. 손보(value "F")는 정상 동작.

### Question
값코드 환경 차이에 강건하게 생보를 판정하고, 사용자에게 개발자 용어·값코드를 노출하지 않으려면?

### Answer
화면 표시 **옵션 텍스트("생보"/"손보") 우선 판정**, 값코드(LF/F)는 fallback으로 강등. 메시지 문구는 회장 확인 드롭다운 라벨("생손보 유형")과 "생보" 선택 안내로 교체.

## 수정 파일 (2개 · allowed scope 내)
1. `extension/content.js`
   - **`isSelInsuranceTypeLife()`** (구 라인 899): 선택 옵션 텍스트를 읽어 `optText.includes("생보")` 우선, `normalizeInsuranceType(value)==="LF"` fallback. `el` 부재 시 fail-closed(false).
   - **insurance_type 스냅샷 값** (구 라인 236~239): 동일 우선순위(text "생보"→"생손보" / text "손보"→"손보", value LF/F fallback)로 정합. 출력 문자열("생손보"/"손보")은 기존 계약 유지 → 다운스트림 `normalizeInsuranceType`/domCrossCheck/서버 계약 **불변**.
   - **사용자 메시지** (구 라인 501): `"화면을 생손보(LF)로 전환한 뒤 다시 시도해주세요."` → `"오마이매니저 상단 '생손보 유형'에서 '생보'를 선택한 뒤 다시 시도해주세요."` (값코드 "(LF)" 제거).
2. `extension/__tests__/life-matrix-routing.test.ts`
   - `domWithSelTextValue(text, value)` 헬퍼 추가.
   - 신규 it 3건: 텍스트 "생보"→true(value≠LF여도), 텍스트 "손보"→false(value≠F여도), 값코드 fallback(빈 텍스트+LF→true / +F→false).
   - 메시지 검증 강화: `toMatch(/생보/)` + `not.toMatch(/\(LF\)/)`.

## ★ 설계 핵심 (회귀 0의 관건)
**LIFE 조건(text "생보" 포함 OR value LF)을 NONLIFE 조건보다 먼저 평가**. 레거시 픽스처의 옵션 텍스트 "생손보"는 부분문자열 "손보"를 포함(하지만 "생보"는 미포함)하므로, 순서를 뒤집으면 value=LF인데도 손보로 오분류되어 기존 테스트가 깨짐. LIFE 우선 평가로 value-LF fallback이 먼저 걸려 **기존 픽스처 수정 0건**으로 회귀 없음. 이는 task 공식 `isLife = optionText.includes("생보") || value==="LF"`와 정확히 일치.

## 테스트 결과
```
npx vitest run extension/__tests__/
Test Files  23 passed (23)
     Tests  501 passed (501)
  Duration  4.89s
```
- 회귀 0. 기존 테스트/픽스처 수정 없이 전체 GREEN.

## L1 스모크테스트 결과
- 서버 재시작: **해당없음** (브라우저 확장 콘텐츠 스크립트 — 서버/API 무관)
- API 응답 확인: **해당없음**
- 실동작 검증: **vitest JSDOM 실 DOM 호출** — 순수 DOM 판정 로직이므로 JSDOM으로 구성한 실제 `<select>`/옵션에 대해 `isSelInsuranceTypeLife`/`captureLifeMatrixToSession`을 실호출하여 판정 결과를 관측(501 tests PASS). 옵션 텍스트 "생보"→생보, "손보"→손보, 값코드 fallback, 메시지 문구까지 실제 함수 실행으로 확인. (실제 오마이매니저 화면 E2E는 사내 로그인 세션 필요 → ANU/회장 rollout 단계에서 확인 대상)
- 스크린샷: 해당없음

## 발견 이슈 및 해결
- TS 진단 경고 2건(`_lastMmlfcpTrace` 라인 191, `snapshot` 라인 2885): **pre-existing**. `_lastMmlfcpTrace`는 origin/main에도 존재(base 라인 191 동일). 라인 2885는 본 변경 +12줄로 shift된 기존 코드. **본 task 변경 hunk(236~251, 513, 915~925) 밖** — 신규 유입 아님. 범위(content.js 판정/문구만) 밖이라 미수정.

## 모델 사용 기록
- 프레이야(프론트엔드): **sonnet** — content.js 판정 로직 + 테스트 구현 (일반 코딩/로직).
- 팀장(오딘, opus): 설계(G1)·회귀 리스크 분석·검토·통합만. 직접 코딩 없음.

## 머지 판단
- **머지 필요**: Yes (단, merge_policy=none → **ANU가 머지 소유**)
- **브랜치**: task/task-2882-dev2 (push 완료, `d18c75c`)
- **워크트리 경로**: /home/jay/projects/InsuRo/.worktrees/task-2882-dev2
- **머지 의견**: additive·content.js(+테스트) 6줄 수준 surgical. 501/501 GREEN·회귀 0. 다운스트림 계약(insurance_type 문자열/normalize/서버) 불변. 손보(F) 동작 보존. ANU 독립검증(clean worktree vitest) 후 머지 권장. 새 확장빌드 전송·rollout은 ANU/회장.

## 비고
- 확장 manifest·background·src·server **불변**. life_matrix 라우팅·consent·egress·taint-guard 로직 **불변** — 판정 기준(text 우선)과 메시지 문구만 변경.

## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회

