# task-2903 — 소식지 검토 UI v2 (원문↔정리본 대조 + 숫자·의미 확인 게이트)

- 팀: dev2 (오딘) · 담당 구현: 프레이야(sonnet, 프론트) · 레벨: Lv.3
- 프로젝트: InsuRo (webapp src/ only)
- 브랜치: `task/task-2903-dev2` · base: **4cf8dd5**(origin/main, task-2901 포함) · HEAD: **dca05a1**
- 워크트리: `/home/jay/projects/InsuRo/.worktrees/task-2903-dev2`

## S (상황)
소식지 AI 정리본을 사람이 발행 전 검토하는 UI(task-2901, v1)가 이미 있었으나, v1은 **보험사명을 마스터 강제 select + 미등록 hold 게이트**로 잠그고 승인 게이트를 보험사명/숫자/개정일 3체크박스로 두었다.

## C (문제)
회장 260805 초점 교정: **보험사명·개정일은 신뢰 대상 → 확인 게이트/마스터 강제 금지.** 진짜 확인 대상은 **① 숫자 오인식 ② 본문 의미 왜곡** 뿐. v1의 초점이 회장 의도와 어긋남.

## Q (핵심 질문)
기존 컴포넌트를 어떻게 재초점화해 (a) 보험사명을 단순 인라인 편집으로 되돌리고 (b) 승인 게이트를 숫자·의미 2종으로 축소하며 (c) number_misread/meaning_drift를 원문 대조 3열로 부각할 것인가?

## A (해결)
`src/components/newsletter/` 5개 파일만 수정(순수 프론트, server/·extension/·.github/ 불변).

### 수정/신규 파일
- `reviewApi.ts` (+12) — `NumberMisreadDetail`(summary_value/source_quote/issue), `MeaningDriftDetail`(summary_text/source_quote/issue) 타입 추가(순수 추가).
- `ValidationFlags.tsx` (+94/-1) — `NumberMisreadCard`(정리본 숫자/원문/문제 3열), `MeaningDriftCard`(정리본 의미/원문/문제 3열) 신규. 분기: cross_model_disagree/number_misread/meaning_drift → 특수 3열, 그 외 → GenericFlagRow. 하단 안내는 과정형("…대조해 확인하세요")으로 결론형 회피. `data-testid` 부여.
- `ReviewDetailPanel.tsx` (49줄 변경) —
  - 보험사명: `Select`(+마스터 fetch/insurerKnown/hold 경고) 전부 제거 → 일반 `Input`(인라인 편집).
  - 게이트: `GATE_ITEMS` 3종 → **2종**(`numbers`="숫자 원문 대조 확인", `meaning`="본문 의미(담보 조건·적용대상) 원문과 일치 확인"). `canApprove`에서 insurerKnown 조건 제거 → **둘 다 체크해야 승인 가능**.
  - HIGH 강조: number_misread/meaning_drift HIGH 개수를 각각 세어 게이트 상단에 빨간 텍스트로 "⚠️ 숫자 오인식 n건 · 의미 왜곡 n건 — 좌측 대조에서 반드시 원문과 확인 후 체크하세요"(0건이면 미렌더).
  - 제목/본문/전이버튼(교정·반려·재추출·발행)·edited payload는 그대로.
- `ValidationFlags.test.tsx` (+44), `ReviewDetailPanel.test.tsx` (신규) — 3열 렌더 testid·게이트 2체크→승인 활성화·보험사명 Input(마스터 select 부재) 검증. (신규 test에 로컬 ResizeObserver 폴리필 추가; 전역 setup.ts는 범위 밖이라 미수정.)

### 검증 결과
- `npx tsc --noEmit`(broad) — 우리 파일 에러 **0**. (tsconfig.app 기준 잔존 6건은 전부 우리 diff 밖 파일=CommunityBoard/AdminSubscriptions/HistoryGroupCard.test/use-user-tokens.test/sw-bypass → newsletter 미참조, 구조적 pre-existing.)
- `npx vitest run src/components/newsletter/` — **15/15 PASS** (ReviewQueue 5 / ValidationFlags 6 / ReviewDetailPanel 4).
- `npm run build` — **exit 0** (dist/index.html, PWA sw.js 생성).

## L1 스모크테스트 결과
임시 Vite 하버스(reviewApi.fetchReviewDetail 목업 오버레이 + dummy env)로 **실제 컴포넌트를 실브라우저 렌더** → Playwright 스크린샷 육안. 검증 후 목업/하버스/.env.local 전부 제거, worktree clean 복원(HEAD=dca05a1).
- **서버 재시작**: 성공 (vite dev :5177, 하버스 HTTP 200)
- **API 응답 확인**: 해당없음(백엔드 미기동, reviewApi 목업으로 대체 — number_misread/meaning_drift 플래그는 server/ 금지 경로라 목업 스키마로 렌더 검증)
- **단위테스트(vitest)**: `Test Files 3 passed (3)` · `Tests 15 passed (15)`
- **콘솔 에러**: 0건
- **스크린샷**:
  - `memory/reports/assets/t2903-review-detail-full.png` — 2-pane(좌 원문/우 필드), 보험사명=Input("삼성화재", Select 아님), number_misread 3열(정리본 30,000만원 / 원문 3,000만원 / 문제 자릿수 오인식), 게이트 강조 "⚠️ 숫자 오인식 1건 · 의미 왜곡 1건". 레이아웃 겹침 없음.
  - `memory/reports/assets/t2903-gate-both-checked.png` — 숫자·의미 2체크박스 모두 체크 → **승인 버튼 disabled 해제(활성화)** 실동작 확인.
- **육안 확인 항목(전부 PASS)**: number_misread·meaning_drift 3열 대조 렌더 / 2-pane / 보험사명 마스터 강제 select·hold 게이트 **없음** / 승인 게이트=숫자·의미 2체크박스만 / 둘 다 체크 전 승인 불가 → 둘 다 체크 시 승인 가능 / cross_model_disagree·generic 렌더 유지.

## 머지 판단
- **머지 필요**: Yes (Lv.3, --action pr)
- **브랜치**: `task/task-2903-dev2`
- **워크트리**: `/home/jay/projects/InsuRo/.worktrees/task-2903-dev2`
- **머지 의견**: 순수 additive 프론트 5파일(components/newsletter/). base=4cf8dd5 clean, diff 5파일뿐. tsc 0(우리 파일)/vitest 15·15/build 0/실렌더 육안 전항목 PASS. 회장 초점 교정 정확 반영. **완결성 순서 B** — ANU 독립검증(clean worktree 실렌더)·머지·배포는 ANU 소관.

## 발견 이슈/한계
- 백엔드(newsletter_validation.py)는 아직 number_misread/meaning_drift 규칙을 생산하지 않음(server/ 금지 경로). UI는 회장 스펙의 detail 스키마로 목업 렌더 검증. **백엔드 플래그 생산은 별도 태스크 필요**(후속).
- jsdom ResizeObserver 부재 → 신규 test 로컬 폴리필로 우회. 전역 `src/test/setup.ts` 추가는 후속 검토.
- task 파일의 base(a914594)는 stale이었음 → 실제 origin/main=4cf8dd5(task-2901 포함) 기준으로 작업.

## 모델 사용 기록
- 프레이야(프론트, 구현+테스트+lint fix): **sonnet** (일반 코딩/로직). 팀장(오딘, opus)은 설계/검토/L1 실렌더 검증만 수행, 직접 코딩 없음.

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


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


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

