# task-2889 보고서 — 담보명 코드 노출 버그 수정 (캡처 담보명 병합 + 전 표 미분류 가드)

## Situation
회장 실사용 중 상담 결과지에서 **담보명이 아니라 코드(a042·b002 등)가 노출**되는 버그(특히 상단 "선택 담보" 표). 원인:
- 담보명 해석이 `fetchCoverageNameMap`(카탈로그 맵) **단일 의존** → fetch 실패(미인증/네트워크/non-ok=`{}`)나 코드 누락 시 raw 코드로 fallback.
- `SelectedCoveragesBlock`이 `resolveCoverageName(cd, nameMap)`만 호출 — **명시적 담보명 미전달 + "미분류" 가드 없음** → raw 코드 그대로 노출.
- 저장된 `analysis_matrix.coverages[].name`(캡처 담보명)이 이름 해석에 활용되지 않음.

## Complication
- RpPresentation의 전체담보 표들은 이미 `DisplayCovName` 가드(미분류)가 있으나, ConsultationHistoryView의 선택담보 표에는 가드가 없어 코드가 새어나감.
- 카탈로그 fetch가 실패하면 캡처 이름이 있어도 표시되지 않음.

## Question
캡처된 담보명을 이름 해석에 병합해 카탈로그 실패에도 실제 담보명이 표시되게 하고, 모든 담보표에서 raw 코드 노출을 0으로 만들려면?

## Answer (surgical 수정)
### 1. 캡처 담보명 보조맵 구성 → 병합 (우선순위: 캡처 name > 카탈로그 맵 > 코드)
- `coverageCatalog.ts`에 헬퍼 추가:
  - `coverageNameMapFromMatrix(matrix)` — 매트릭스 `coverages[]`에서 `{cd→name}` 유효 사람이름만 추출(cd동일/코드패턴/공백 제외).
  - `mergeCoverageNameMaps(...maps)` — 뒤 인자 우선 병합(null/undefined 무시).
  - `resolveCoverageDisplay(cd, map, name)` → `{label, isCode, code}` — 코드패턴/cd동일이면 `label="미분류"`, `code`=raw cd(tooltip용).
  - `isCoverageCode(s)` — 코드패턴 판정.
- `ConsultationHistoryView.ConsultationRecordCard`에서 `mergedNameMap = mergeCoverageNameMaps(카탈로그맵, coverageNameMapFromMatrix(analysis_matrix), coverageNameMapFromMatrix(life_matrix))` 구성 → SelectedCoveragesBlock·CompositeComboSection(→ RpPresentation·LifeThreeCriticalDiff)에 전파. 캡처 이름이 카탈로그 실패에도 표시됨.

### 2. 모든 담보표 raw 코드 노출 0 (공용 가드 통일)
- `RpPresentation.DisplayCovName`을 `resolveCoverageDisplay` 공용 헬퍼로 리팩터 + **export**(로컬 `COVERAGE_CODE_PATTERN` 제거, lib로 일원화).
- `SelectedCoveragesBlock`: raw `resolveCoverageName(...)` 텍스트 → `<DisplayCovName cd map />` 가드 적용(미분류 + code는 title 툴팁만).
- 생보표: `lifeThreeCritical.ts`의 `computeLifeThreeCriticalView` coverageName 산출부에 코드패턴 가드(미분류). 계산·수치·매칭 로직은 무변경.

## 수정 파일 목록 (7개 · 전부 allowed_resources 범위, forbidden 0)
- `src/lib/coverageCatalog.ts` — 헬퍼 4종 추가(+56)
- `src/lib/lifeThreeCritical.ts` — view coverageName 코드가드(+5/-3)
- `src/components/composite/RpPresentation.tsx` — DisplayCovName 공용가드 리팩터+export
- `src/components/composite/ConsultationHistoryView.tsx` — 병합맵 구성+전파, SelectedCoveragesBlock 가드
- `src/lib/__tests__/coverageCatalog.test.ts` — 신규 9
- `src/lib/__tests__/lifeThreeCritical.test.ts` — 신규 1(코드가드)
- `src/components/composite/__tests__/ConsultationHistoryView.test.tsx` — 갱신 2 + 신규 2

## 테스트 결과
- `npx tsc --noEmit`: **0 에러**
- `npx vitest run` (전체): **1098 passed / 73 files** (베이스라인 1088 → **+10, 회귀 0**)
  - 신규 검증: 카탈로그 빈맵+매트릭스 name 있음→담보명 표시 / 둘 다 없음→미분류 / 병합 우선순위 / 코드패턴 노출 0.
  - 갱신: 기존 "코드 fallback 노출" 테스트 2건(C001/C002·zzz999)은 **버그 그 자체를 검증하던 것** → "미분류" 표시로 정정.
- 프로덕션 빌드: `npm run build` **성공(exit 0, ✓ 12.13s, dist 재생성)**. (chunk>500KB 경고는 기존 이슈)

## L1 스모크테스트 결과 (실제 Chromium 브라우저)
- **서버 재시작**: 해당없음(빌드 검증으로 대체) — 단, e2e webServer가 `npm run dev`(:8080)를 실기동.
- **API 응답 확인**: 해당없음(webapp-only, 서버 무변경). e2e는 Supabase/InsuRo mock 라우트로 구동.
- **e2e (실행·통과)**: `npx playwright test composite-design-vpath.spec.ts` → **3 passed (13.3s)**. 상담이력(COV-001 selected + analysis_matrix + 생보 3대질병) 실브라우저 렌더 통과. (콘솔 에러=kakao CDN integrity/의도된 flag-OFF 403 — 기존 이슈, 본 변경 무관)
- **스크린샷 (육안 검증)**: `/tmp/task-2889-consultation.png`(첨부). 선택 담보 표 + 전체담보 표(section1/2) + 계단식 전부에서 캡처 담보명 **"일반상해"** 표시, raw 코드 **"COV-001" 노출 0** 확인. (임시 스모크 단언 `selected-coverages-table`에 "일반상해" 포함 & "COV-001" 미포함 통과 후 임시 편집 revert — 커밋 clean)

## 발견 이슈 및 해결
- **e2e 픽스처 영향 확인**: composite-design-vpath 첫 레코드가 `analysis_matrix.coverages:[{cd:"COV-001",name:"일반상해"}]` 보유 → 병합 로직으로 선택담보 표가 이제 "일반상해" 표시(개선). e2e는 raw "COV-001" 텍스트를 단언하지 않아 **회귀 없음**(오히려 정상화). 임시 스모크+스크린샷으로 실증.
- **기존 테스트 충돌**: 신규 가드(`resolved===cd`→미분류)로 코드-노출을 단언하던 2개 테스트가 깨짐 → 버그 검증이었으므로 "미분류"로 정정(정당).

## 모델 사용 기록
- 불칸(백엔드, lib/coverageCatalog·lifeThreeCritical + 테스트): **sonnet**
- 이리스(프론트, RpPresentation·ConsultationHistoryView + 테스트): **sonnet**
- 팀장(헤르메스): 설계/분배/통합/검증(전체 tsc·vitest·build·e2e·스크린샷 육안). haiku 미사용.

## 머지 판단
- **머지 필요**: Yes (단, `merge_policy=none` → 머지 주체=**ANU**)
- **브랜치**: `task/task-2889-dev1`
- **워크트리 경로**: `/home/jay/projects/InsuRo/.worktrees/task-2889-dev1`
- **머지 의견**: webapp-only(src/ + tests만), 서버/확장/카탈로그 엔드포인트 무변경. tsc 0·vitest 1098/0(회귀0)·build 성공·e2e 3 passed·스크린샷 육안 GREEN. 충돌 위험 낮음(additive+가드). 순서 B: 봇=push+.done까지, **ANU 독립검증·머지·CF Pages 배포**(`source /home/jay/workspace/.env.keys` → `wrangler pages deploy dist --project-name insuro --branch main`).

## 비고
- 손보 계단식·생보 계단식·수치·색 로직 불변(이름 해석·가드만 수정).
- 생보표는 tsx 편집 불가(allowed 밖)라 tooltip 없이 lib에서 코드→"미분류" 가드. 대부분 `target.label`(한글) fallback이라 미분류는 실이름 없을 때만.

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

