# task-2909 보고서 — 소식지 검토 UI: 제시 증거(플래그)를 본문에 연결 + 숫자·의미 부각/노이즈 정리

- 작업 ID: task-2909 | 팀: dev2-team (오딘) | 레벨: Lv.2 | 프로젝트: InsuRo (webapp, src/ only)
- 브랜치: `task/task-2909-dev2` | base: `origin/main` = `8c26989` | HEAD: `e383da1`
- merge_policy: none → **머지·재배포는 ANU(개발실장)** (순서 B)

## S (Situation)
소식지 검토 상세뷰의 "제시 증거(validation_flags)" 목록이 추상적이라, 리뷰어가 각 플래그가 본문의 어느 부분을 가리키는지 알 수 없었다. 또 회장이 신뢰 대상으로 두는 보험사명·날짜 플래그가 노이즈로 섞여 핵심인 숫자·의미 신호가 묻혔다.

## C (Complication)
- 플래그 카드가 detail(정리본/원문/문제)을 보여주더라도 **본문 pane과 연결되지 않아** "이게 본문 어디?"가 해소되지 않음.
- 모든 플래그가 평면 나열 → 보험사명·날짜 노이즈와 숫자·의미 핵심이 시각적 우선순위 없이 섞임.

## Q (Question)
src/ 2개 컴포넌트만 수정하여 (1) 각 플래그를 본문에 연결하고 (2) 숫자·의미를 상단 강조 + 보험사·날짜를 접이식으로 분리할 수 있는가? 기존 2-pane·교정·전이·게이트 회귀 0으로.

## A (Answer) — 구현

### 수정 파일 (4개, src/components/newsletter/ 만)
1. `ValidationFlags.tsx` — 전면 재구성 (169줄 diff)
2. `ReviewDetailPanel.tsx` — 본문 pane 연동 추가 (59줄 diff)
3. `ValidationFlags.test.tsx` — 테스트 4개 추가
4. `ReviewDetailPanel.test.tsx` — 테스트 2개 추가

### 1) 각 플래그를 본문에 연결
- `number_misread`/`meaning_drift`/`cross_model_disagree`: 기존 3열 대조(정리본/원문/문제) 유지 + 각 카드에 **"본문에서 찾기"** 버튼(`LocateButton`) 추가.
- 그 외 플래그(`GenericFlagRow`): detail에 발췌 필드(`source_quote`/`quote`/`excerpt`/`snippet`)가 있으면 "원문/본문 발췌" 박스로 표시 + 발췌 있으면 "본문에서 찾기" 버튼.
- **본문 pane 연동**(`ReviewDetailPanel`): 버튼 클릭 시 `onLocate(query)` → 우측 본문(body)에서 문구를 `indexOf`로 검색.
  - 찾으면: 앞뒤 24자 컨텍스트 + `<mark data-testid="body-highlight">`로 **하이라이트 발췌 박스** 표시 + 가능 시 textarea `setSelectionRange`(best-effort, disabled 시 graceful).
  - 못 찾으면: **발췌 fallback** ("본문에서 해당 문구를 찾지 못했습니다. 발췌: …") → graceful.
  - query: number=정리본 숫자(summary_value), meaning=정리본 문장(summary_text), cross_model=1차값(primary_value), 그 외=발췌. (정리본 값이 본문에 존재하므로 본문 find에 적합)

### 2) 숫자·의미 부각 / 노이즈 정리
- **우선순위 3버킷 분류** 후 렌더:
  - priority(`number_misread`·`meaning_drift`·`number_manual_verify_required`) → 최상단 **"핵심 신호 — 숫자·의미 (최우선 확인)"** 강조 그룹(red-50 배경/테두리).
  - noise(`insurer*`·`month_key_absent`·`ai_suspect`/`ai_no_grounding`의 insurer/date 필드) → 하단 **"참고 (보험사명·날짜) — N건"** 접이식 그룹, **기본 접힘**.
  - rest(그 외: cross_model_disagree, truncated, table_collapse 등) → 중간, 일반 렌더.
- `cross_model_unavailable` → noise 아님 → 항상 노출 + amber 강조("교차검증 미수행")로 리뷰어가 교차검증 미실행을 인지.
- ⚠️ 분류는 rule 기준 + (ai_suspect/ai_no_grounding일 때만) field 기준 → `missing_field(insurer)` 같은 일반 플래그는 노이즈로 오분류되지 않음(기존 테스트 회귀 방지).

### 제약 준수
- src/ 2개 컴포넌트 + 테스트만. server·extension·.github 무접촉. field_confidence 미노출. 과정형 문구 유지. 기존 2-pane/교정/전이/게이트 로직 불변.

## 테스트 결과
- **vitest**: `ValidationFlags.test.tsx` + `ReviewDetailPanel.test.tsx` → **19 passed / 0 failed** (신규 6개 포함, 기존 회귀 0).
  - 신규: 보험사·날짜 접이식 기본접힘/펼침 · 숫자·의미 상단 강조 배치 · onLocate 콜백 정리본값 호출 · cross_model_unavailable 비접힘 강조 · 본문 하이라이트 mark · 본문 미검출 발췌 fallback.
- **npm run build** (tsc + vite): **PASS**, tsc 에러 0, `✓ built in 12.28s`, dist/ 생성 (11:10).

## L1 스모크테스트 결과
- 서버 재시작: 해당없음(정적 webapp) — 대신 **vite dev(:5199) 기동 + 임시 하네스로 실제 브라우저 렌더**.
- API 응답 확인: 해당없음(백엔드 미변경) — harness HTTP 200.
- 스크린샷: **육안 확인 완료**
  - `memory/reports/t2909-1-default-collapsed.png` — 기본 상태: 상단 핵심 신호(숫자 오인식/의미 왜곡 3열 대조) + cross_model_unavailable 노출 + truncated 발췌 + 하단 "참고(보험사명·날짜) — 3건" **접힘**.
  - `memory/reports/t2909-2-expanded-located.png` — 상호작용: "본문에서 찾기" 클릭 시 하이라이트 대상 에코("1,000만원") + 접이식 펼침 시 insurer_ungrounded·month_key_absent·ai_suspect(insurer) 3건 분리 표시.
  - Playwright a11y 스냅샷으로 DOM 구조/순서/접힘상태/onLocate 동작 교차검증. 콘솔 에러 0건. browser_close + vite kill + 하네스 삭제 완료(잔존 프로세스 0).
  - 비고: 임시 하네스는 앱 전역 Tailwind CSS를 로드하지 않아 시각 스타일은 단순화되어 보이나(카드 테두리/그리드 미적용), 클래스는 유효한 Tailwind이며 build PASS. 구조·내용·상호작용·우선순위·접힘은 정확히 검증됨. 앱 통합 실렌더(CSS 포함)는 ANU 독립검증 권장.

## 발견 이슈 및 해결
- Playwright MCP 스크린샷 저장 위치가 메인 cwd(`teams/dev2/`)였음 → reports로 복사 후 원본 정리(완료).
- InsuRo 원격 리포 이전("repository moved") 경고 → push는 리다이렉트로 정상 반영. `git ls-remote` 로 **원격 head e383da1 == 로컬 HEAD 일치 확인**(메모리 교훈 feedback_finish_task_verify_remote_head_push_260805 적용).

## 머지 판단
- **머지 필요**: Yes (단, merge_policy=none → ANU가 수행)
- **브랜치**: `task/task-2909-dev2`
- **워크트리 경로**: `/home/jay/projects/InsuRo/.worktrees/task-2909-dev2`
- **머지 의견**: src/ 순수 additive(UI-only), 백엔드/스키마 무관, 회귀 0, build PASS. ANU 독립검증(앱 통합 실렌더 CSS 포함) 후 머지·CF Pages 재배포 권장.

## 모델 사용 기록
- 프레이야(프론트, 구현) — **sonnet** (일반 코딩/로직). 팀장(오딘, opus) — 설계/검토/빌드·실렌더 검증/통합. haiku 미사용.

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

