# [Lv.3] 소식지 검토 상세 UI 재설계(레이아웃 B) + 플래그별 개별 확인(ack) 게이트

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "src/components/newsletter/ReviewDetailPanel.tsx"
    - "src/components/newsletter/ValidationFlags.tsx"
    - "src/components/newsletter/reviewApi.ts"
    - "src/components/newsletter/**/*.test.tsx"
  forbidden_paths:
    - ".github/**"
    - "extension/**"
    - "server/**"
  commands: ["npm","npx","vite","git"]
  merge_policy: "none"
  ttl_hours: 20
```
> ★ base=현 origin/main. 근거: agent 미팅 4사이클 합의(회장 레이아웃 B 선택). 미팅 기록: `memory/meetings/2026-08-06-newsletter-review-detail-ui.md`.

## 배경 (회장 피드백 + 미팅)
현 검토 상세 2-pane가 (1)보기 어렵고 (2)좌측 제시증거에 스크롤 래퍼 없어 HIGH 플래그가 잘림. 근본원인=flex 자식 `min-h-0` 누락. 회장 선택 = **레이아웃 B**.

## 작업 1 — 레이아웃 B (스크롤 골격)
```
[상단]  얇은 sticky 요약 스트립 (항상 보임) + 그 아래 bounded(≤26vh) 플래그 카드영역(자체 스크롤)
[하단]  원본(이미지) | 마크다운(추출본, 뷰↔편집)  ← flex-1 로 세로 대부분 차지 (원본 대조 크게)
[최하단] sticky 액션바 (승인/반려/재추출) — 스크롤로 안 사라짐
```
- 모달 `h-[90vh] flex flex-col overflow-hidden`. 상단 결과 `shrink-0`(요약스트립 auto + 카드 `max-h-[26vh] overflow-y-auto`). **하단 `flex-1 min-h-0 grid grid-cols-2 divide-x`**, 각 pane `min-h-0 min-w-0 overflow-auto`. 액션바 `shrink-0`. 모든 스크롤 노드 `min-h-0`.
- **요약 스트립**: 🔴 숫자 N · 🟠 의미 N · **미확인 HIGH N** · (편집중이면 dirty 뱃지). 항상 보임.
- **좌하 원본**: `source_file_ref.file_url` 이미지 표시(이미지면 `<img>`, 아니면 링크). ★ 이미지 위 하이라이트는 불가 → 플래그 선택 시 원본 위 **"원문 발췌 대조" 배너**(source_quote 텍스트)만. (페이지 스크롤은 데이터에 pages[] 없어 no-op — 흉내 금지.)
- **우하 마크다운**: 뷰(기본)=`<div>` 렌더(하이라이트 가능) ↔ 편집 토글=Textarea 풀높이. 플래그 선택 시 summary_value 를 `<mark>`+`scrollIntoView` 하이라이트.
- 3열 미니카드 잘림 → **세로 대조**(문제 크게 + 정리본↔원문 색 diff), `min-w-0 break-words tabular-nums`, container query(`@container @md:`)로 좁으면 세로 스택.

## 작업 2 — 플래그별 개별 확인(ack) 게이트 (전역 체크박스2 폐기)
- **각 HIGH 플래그 카드에 "원문에서 직접 대조 확인함" 체크(attestation)**. 전역 "숫자 확인/의미 확인" 2체크박스 제거.
- **미확인 HIGH 카운트 = 전체 validation_flags 중 level=='HIGH' 총수 기준**(접힌/미렌더 플래그 포함 — 렌더분만 세면 잘림사고). `unconfirmedHigh = HIGH총수 - attested HIGH수`.
- **승인 버튼**: `disabled = unconfirmedHigh>0 || dirty || busy || status!=='pending_review'`. `aria-describedby`로 왜 막혔는지 안내(role=status aria-live).
- **편집 시작 → 모든 ack 무효화**(dirty=true), 저장 후 서버 재검증된 새 flags로 갱신되면 ack는 빈 상태 유지.
- **grounding 근거 없는 HIGH 표식**: 플래그 detail 에 정확 인용(source_quote/span)이 없으면 **"⚠ 원문 근거 없음 — 육안 필수" RED 뱃지**(기계가 못 짚은 곳 = 사람이 가장 봐야 할 곳).

## ★ 공유 계약 — flag_key & approve 요청 (백엔드 태스크와 100% 동일)
- flag_key(결정론): `sha256(rule + "|" + field + "|" + (detail.source_quote || detail.summary_value || detail.summary_text || "") + "|" + message).hex[:16]`. (백엔드가 동일 알고리즘으로 서버 검증.)
- **승인 API 호출 시 바디에** `acknowledgements: [{flag_key, attested:true}]`(attested된 HIGH 전부) 포함. 서버가 HIGH 집합을 자체 계산해 대조·fail-closed 하므로, 프론트는 정확한 flag_key로 보낼 것.

## 제약
- src/ 만(위 4파일). server·extension 불변. 보험사명/제목/본문 편집·전이(반려/재추출)·기존 기능 회귀 0. field_confidence 미노출. 과정형 문구.

## 검증
- `npm run build` PASS + tsc 0. 신규 테스트: min-h-0 독립스크롤(플래그 많아도 안 잘림)·요약스트립 카운트=HIGH총수·개별 ack 전 승인 disabled·모든 HIGH ack 후 enable·편집시작→ack무효화·근거없는 HIGH RED뱃지·flag_key 알고리즘 고정 픽스처 일치.
- ★ **실렌더 스크린샷 육안 필수**(vite/harness, 목업 flags): 레이아웃 B(얇은 상단+큰 하단 2-pane), 플래그 개별 확인 체크, 승인 disabled 사유 표시, 세로 대조카드 안 잘림.

## 완료 (★ 순서 B)
- src/ 만. **dev6 금지** — dev2(오딘, 검토 UI 원저자). 커밋 → push → **★ push 확인** → **npm run build PASS 확인** → finish-task foreground 1회 → .done. ANU 독립검증(실렌더)·머지·배포는 ANU.

## goal_assertions (auto-generated)
- `npm run build`
