---
task_id: "2857"
team: 2팀
level: 3
priority: P2
depends_on: []
created_at: 2026-07-25T16:00:00+09:00
deadline: null
status: completed
scope: task
---

# task-2857 — InsuRo 확장 플로팅 카드 내부 UI 업그레이드 (버튼 명확화 + 보험료 테이블 + 디자인 폴리시)

## S (Situation)
InsuRo 확장(Chrome content script)의 우측 하단 플로팅 캡처 카드가 뜨긴 하지만 내부가 **raw 텍스트** 상태였다. 클릭 버튼이 버튼처럼 안 보이고, 보험사별 보험료가 그냥 나열돼 가독성이 떨어졌다. 회장 피드백: (1) 클릭 버튼을 직관적 버튼으로, (2) 보험사별 보험료를 테이블로, (3) 전반 내부 디자인 업그레이드.

## C (Complication)
- 캡처·동의(consent)·single-egress·taint-guard·CRM 매칭·저장 로직은 계약(§1~§9)으로 동결돼 있어 **절대 불변**. 렌더/구조/스타일만 손대야 함.
- 대상 파일은 `extension/content.js` 단일(2,626줄) + 테스트. `merge_policy=none` — 머지는 ANU 권한.
- XSS 방지 관례상 `innerHTML` 금지, `createElement`+`textContent`만 허용.
- 기존 element ID를 테스트가 조회하므로 ID 제거/변경 금지.

## Q (Question)
로직 0 변경·회귀 0 조건에서 플로팅 카드 내부를 버튼 위계 + 보험료 테이블 + 디자인 폴리시로 업그레이드할 수 있는가?

## A (Answer)
가능. 렌더/스타일만 수정하여 완료. 전체 424 tests PASS(회귀 0), 실 렌더 코드 기반 브라우저 스크린샷으로 시각 검증 완료.

---

## 수정 파일 목록
- `extension/content.js` (수정) — 렌더/스타일만
  - `INSURO_BRAND_COLOR`: `#1a56db` → `#2563eb` (팔레트 primary 통일)
  - `ensureInsuroFloatingPanelStyle(d)`: 주입 `<style>` 전면 확장 — 카드 컨테이너·헤더·섹션 헤딩·보험료 테이블(zebra/최저가 강조)·검증 뱃지(ok/warn)·버튼 3위계(Primary/Secondary/Tertiary + disabled)·입력 필드/라벨·상태 안내. 모든 셀렉터 `#insuro-floating-panel` 스코프(페이지 CSS 충돌 방지).
  - `attachOhmyPpdPreviewButton`: "📊 보험료 조회" 섹션 헤딩 추가
  - `renderOhmyPpdPreview`: 보험료 미리보기를 `div.insuro-ppd-preview-row`(span 나열) → `<table class="insuro-premium-table">`(thead 3열: 보험사명/월 보험료/검증 + tbody)로 전환. WITHIN_TOLERANCE 행 = `td.insuro-premium-value`(screen_sum만, computed_sum 승격 금지) + `span.insuro-badge-ok`("허용오차 이내 · 최종 검증 전" 정직 문구 유지). blocked 행 = "지금 확인이 어려워요" 유지. WITHIN_TOLERANCE 중 screen_sum 최솟값 행에 `tr.insuro-premium-lowest` 강조.
  - `attachCrmMatchControls`/`buildCrmCreateForm`: "👤 고객 확인"/"🆕 신규 고객 등록" 섹션 헤딩 class 부여
- `extension/__tests__/task-2857-ui-upgrade.test.ts` (신규) — 8 케이스: 테이블 구조(thead/tbody/tr)·뱃지+보험료 포맷·최저가 강조(다사/동점/단일/전체blocked)·주입 style 규칙 포함·버튼 회귀

## 버튼 위계 매핑
- Primary(동의하고 저장) = `#insuro-consent-save-btn` (파란 채움, width 100%)
- Secondary(고객검색) = `#insuro-crm-search-btn` (흰 배경 + 파란 테두리)
- Tertiary(신규 등록) = `#insuro-crm-create-btn`, `#insuro-crm-new-btn` (회색)

## 테스트 결과
- `npx vitest run extension/__tests__/` → **Test Files 20 passed (20) / Tests 424 passed (424)** (베이스라인 416 + 신규 8, 회귀 0)
- 정적: `npx tsc --noEmit` 신규 에러 0 (line 191 `_lastMmlfcpTrace`, `attachCrmMatchControls` snapshot 미사용은 **기존** 이슈 — main 동일)

## L1 스모크테스트 결과
- **서버 재시작**: 해당없음 (Chrome 확장 content script — 서버 프로세스 없음)
- **실 렌더 검증**: 실 `content.js`(vitest 인터롭으로 import) → `attachOhmyPpdPreviewButton` + `handlePpdPreviewClick`(VALID 상태) + `renderOhmyPpdPreview`(다사 렌더모델) 실행 → 실제 생성된 `#insuro-floating-panel` outerHTML + 주입 style을 HTTP 서빙 → Playwright 스크린샷
  - 프로그램 검증: table=true, badge-ok=3, lowest=true, save-btn=true, search-btn=true
- **스크린샷**: `/home/jay/workspace/teams/dev2/insuro-2857-floating-card.png` — 헤더바 파랑(#2563eb)+최소화 토글, 보험료 테이블(보험사명|월 보험료|검증, zebra), 초록 검증 뱃지 3개, **삼성화재 최저가 행(28,500원) 파란 좌측보더+연파랑 강조**, 한화손해보험 blocked "지금 확인이 어려워요"(뱃지·강조 없음), 고객 확인 섹션(이름/생년월일 입력 styled), Secondary "고객 검색", Primary "인슈로에 동의하고 저장"(잠금 disabled) — 스펙 완전 부합. (섹션 헤딩 이모지는 headless 폰트 부재로 네모 표시되나 실 Chrome 정상 — 코드 이슈 아님)
- **browser_close 호출 완료**, Chrome 잔존 프로세스 0

## 로직 불변 확약
`handlePpdPreviewClick`·`handleConsentSaveClick`·`handleCrmSearchClick`·`handleCrmCreateClick`·`formatKoreanMobile`·`isValidKoreanMobile`(휴대폰 3-4-4)·`buildAnalysisMatrix`·`getPreviewSnapshot`·`isSaveUnlocked`·`INSURO_CONSENT_VERSION/SCOPE/SOURCE` 전부 diff 미등장(본문 로직 불변). `innerHTML` 신규 사용 0건. consent.scope=`CONSULTATION_HISTORY_SAVE` 회귀 테스트 PASS 유지.

## 빌드
- 대상은 `extension/content.js`(정적 서빙 content script) — 웹앱 `npm run build` 대상 아님. 별도 빌드 불필요. 확장 재패키징(zip)은 ANU 몫.

## 모델 사용 기록
- 프레이야(프론트엔드, content.js 구현 + 렌더 테스트): **sonnet** — 일반 코딩/렌더 로직
- 헤임달(테스터, 독립 회귀 검증 + 엣지 테스트 3건 보강): **sonnet** — 검증/분석
- 팀장(오딘, Opus): 설계·분배·diff 리뷰·L1 스모크·통합만. 직접 코딩 없음. haiku 미사용.

## 머지 판단
- **머지 필요**: Yes — 단, `merge_policy=none` → 머지는 **ANU 권한** (봇 머지 금지)
- **브랜치**: `task/task-2857-dev2` (origin push 완료)
- **워크트리 경로**: `/home/jay/projects/InsuRo-worktrees/task-2857-dev2`
- **커밋**: `e24e985`
- **머지 의견**: 로직 0 변경(렌더/스타일만), 424 tests PASS(회귀 0), 실 렌더 스크린샷 스펙 부합. 충돌 위험 낮음(content.js 단일, 최근 main과 base 정합). ANU 독립 검증 + Codex 반증 리뷰 후 머지 권고. 머지 후 확장 재패키징(zip) → 새 파일럿 전송은 ANU.

## 발견 이슈 및 해결
- (해결) 신규 테스트에서 `lastConsumedEntryStartTime` 모듈 스코프 신선도 게이트(A4-2 계약)로 인해 테스트 간 previewState VALID 재진입 타임아웃 → 매 테스트 단조 증가 `startTime` fixture로 해소. content.js 로직 무변경(테스트 fixture 이슈).
- (정리) 신규 테스트 미사용 `vi` import 제거(진단 hygiene).

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

