# task-2854 보고서 — 확장 UI 확장 (floating 패널 + 휴대폰 3-4-4 + consent.scope 정정 + JWT 안내)

- 팀: dev2-team (오딘)
- 레벨: Lv.4 / 한정승인 (merge_policy=none)
- 브랜치: `task/task-2854-dev2` (base=origin/main d2de7b6, 커밋 6500083)
- 프로젝트: InsuRo (확장 프로그램)

## S (Situation)
파일럿 실 왕복은 성공했으나(캡처→저장→조회), 확장 캡처 UI 3종 개선 + consent.scope DB CHECK 위반 근본수정이 필요했다. 회장 피드백 + Codex 조율로 A/B/C/D 4개 파트 확정.

## C (Complication)
- consent.scope 계약이 content.js·ingest.js·골든/fixture·서버에 얽혀 있어(옛 값 `consultation_history_ingest` vs 서버 요구 `CONSULTATION_HISTORY_SAVE`), 조율 없이 한 곳만 바꾸면 계약 파손.
- floating 패널 재구성은 단순 1함수가 아님 — consent/CRM attach·invalidation 렌더가 "flow-layout 앵커 afterend 삽입"을 가정해 삽입지점 재구성 필요.
- 휴대폰 정규화 전송은 기존 테스트(하이픈 없는 verbatim 기대)와 정면 충돌.

## Q (Question)
캡처/egress/consent/taint 로직을 **한 바이트도 건드리지 않고** 렌더·입력포맷·상수·안내만 바꿔 4개 파트를 계약 정합 상태로 완성할 수 있는가?

## A (Answer) — 구현
### A. Floating 패널 (content.js)
- 신규 `ensureInsuroFloatingPanel(d)` / `ensureInsuroFloatingPanelStyle(d)`: `document.body`에 `#insuro-floating-panel` 고정 카드 (`position:fixed;right/bottom:20px;z-index:2147483000`, 둥근모서리·그림자·흰배경·width 360px·max-height 70vh). 헤더(`#insuro-panel-header`, 브랜드색 `#1a56db` + "InsuRo" + 최소화 토글 `#insuro-panel-toggle`) + 컨텐츠(`#insuro-panel-body`).
- `attachOhmyPpdPreviewButton`이 anchor afterend 대신 카드 body에 btn/status/preview append. **기존 ID·이벤트 핸들러·하위 afterend 체인 전부 불변** → consent/CRM/lock 렌더 로직 무수정으로 카드 안에서 동작. XSS-safe(textContent only).

### B. 휴대폰 3-4-4 자동포맷 (content.js)
- 순수함수 `formatKoreanMobile(raw)`(숫자만·11자리 절삭·3-4-4 하이픈·부분입력 대응), `isValidKoreanMobile(f)`(`/^010-\d{4}-\d{4}$/`). module.exports 노출.
- 신규 고객 폼 phone input에 `input` 이벤트로 즉시 자동포맷. 제출 시 정규화 후 검증 실패면 `CRM_PHONE_INVALID_FORMAT` 한국어 안내로 저장 차단. 서버에는 `010-1234-5678` 정규화 형태로 전송.

### C. consent.scope 정정 (근본수정)
- content.js `INSURO_CONSENT_SCOPE` + ingest.js `CONSENT_SCOPE` → **`"CONSULTATION_HISTORY_SAVE"`** (서버/DB 013 CHECK 요구값과 정합).
- 골든/fixture/scope 테스트 coordinated 갱신: `tests/contract/ohmy_ppd_v2.golden.json`·`generate_golden.mjs`·`prd1-ingest-core`·`prd1-canary-sink-spy`·`contract-golden`·`prd1-background-dispatcher`. golden 재생성 diff=0 확인.
- 잔존 `consultation_history_ingest` = **0건** (전 파일 grep 확인).

### D. JWT 연결 안내 (자동 push 없음)
- `renderJwtSetupNotice` / `removeJwtSetupNotice`: TOKEN_ABSENT 분기에서 `#insuro-jwt-setup-notice`에 "InsuRo 계정 연결 필요" + `https://insuro.biz/composite-design/setup` `target=_blank` 링크. 기존 fail-closed 게이트 불변, 자동 주입 없음.

## 수정/생성 파일 (9 수정 + 1 신규, 전부 allowed_resources 내)
- `extension/content.js` (+166줄)
- `extension/background/ingest.js`
- `extension/__tests__/{contract-golden,prd1-background-dispatcher,prd1-canary-sink-spy,prd1-ingest-core,prd2-crm-ui}.test.ts`
- `extension/__tests__/task-2854-phone-and-floating.test.ts` (신규, 17 테스트)
- `tests/contract/{generate_golden.mjs,ohmy_ppd_v2.golden.json}`
- 금지 파일(manifest.json·crm.js·src/**·server/**) **미접촉** — git status 교차확인.

## 테스트 결과
- goal_assertion `npx vitest run extension/__tests__/` → **19 files / 416 tests / failed 0**.
- 회귀 수정: `prd2-crm-ui.test.ts` phone 기대값 → `010-1234-5678`(B-3 스펙 정합, 서버 verbatim 저장 + 회장 010-1111-2222 표시 요구).
- 신규: formatKoreanMobile 7 + isValidKoreanMobile 5 + floating 렌더 4 + consent scope 회귀 1.

## L1 스모크테스트 결과
- 서버 재시작: 해당없음 (브라우저 확장 — 서버 무변경).
- API 응답 확인: 해당없음.
- 파일럿 빌드: `node scripts/build-pilot-extension.mjs` **성공**. 산출물 `dist-pilot/extension/` (2026-07-25 12:49), `ingest.js` 파일럿 flag `INSURO_CONSULTATION_HISTORY_V1_ENABLED=true`(1회 치환) 확인, content.js에 floating/formatKoreanMobile/CONSULTATION_HISTORY_SAVE 반영 확인.
- JSDOM 실동작(스크린샷 대체): floating 패널 4종 테스트가 실제 DOM에 panel/header/toggle/btn/status/preview 생성·삽입 + 토글 클릭 재현 → pass. (확장 content script는 ohmymanager 실페이지 없이는 Playwright 재현 불가 → JSDOM 렌더 + 파일럿 빌드가 L1 증거.)

## 발견 이슈 및 해결
1. **phone 정규화 vs 기존 테스트 충돌**: 스펙 B-3(정규화 전송)이 정답 → `prd2-crm-ui.test.ts` 기대값 갱신으로 해소.
2. **floating을 body에 붙이며 anchor.nextElementSibling 변화**: 신규 테스트 어서션을 `panel.contains(btn)` 방식으로 정정.
3. **content.js:2303 `snapshot` 미사용 경고**: git diff 확인 결과 task-2836 유래 기존 코드 — 로직 영향 우려로 미변경(범위 밖).

## 모델 사용 기록
- 프레이야(프론트, content.js A/B/C-const/D): **sonnet**
- 토르(백엔드/계약, ingest.js + fixture): **sonnet**
- 헤임달(테스터, 통합/신규테스트/L1): **sonnet**
- haiku 미사용. 팀장(오딘/Opus) 직접 코딩 0 — 전량 위임.

## 머지 판단
- **머지 필요**: Yes (단, merge_policy=none → **ANU가 검증·머지**)
- **브랜치**: `task/task-2854-dev2` (push 완료, 커밋 6500083)
- **워크트리 경로**: `/home/jay/projects/InsuRo/.worktrees/task-2854-dev2`
- **머지 의견**: goal_assertion 그린(416/416), 계약 scope 양방향 정합·잔존 0, 금지파일 미접촉, 파일럿 빌드 정상. 캡처/egress/consent/taint 로직 불변(렌더·포맷·상수·안내만). ANU 독립검증 후 머지 + 새 파일럿 빌드 재전송 권장.

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

