---
task_id: task-2401
type: context
scope: task
created: 2026-05-03
updated: 2026-05-03
status: in-progress
---

# 맥락 노트: task-2401

**task**: task-2401

---

## 결정 근거

### 핵심 결정 1: 새 `_satori.py`를 `skills/satori-cardnews/`에 생성 (hybrid-image 변경 금지)

**근거**:
- task에 명시: `skills/hybrid-image/**` 변경 금지
- 1차 silent corruption 원인은 `skills/hybrid-image/patterns/_satori.py:131-135` Pillow fallback (Node.js 실패 시 한글 미지원 PIL default font 사용 → tofu □□□)
- `skills/satori-cardnews/_satori.py`로 새 진입점 생성 → 향후 satori 호출은 이 모듈을 사용
- hybrid-image의 _satori.py는 격리 (deprecated 주석으로 안내, 코드 자체는 무수정)

**대안과 기각**:
- (A) hybrid-image 직접 수정 → **기각**: task 변경 금지 명시
- (B) tools/ai-image-gen/satori_cli.js 수정 → **기각**: allowed_resources에 미포함
- (C) 새 모듈 분리 → **채택**: 책임 분리, 회귀 0, 향후 마이그레이션 점진적 가능

### 핵심 결정 2: tesseract OCR 대신 pixel-based 검증으로 대체

**근거**:
- 환경 제약: tesseract 미설치, sudo 비번 미보유 → apt install 불가
- task 의도(silent pass 차단)는 더 강력한 픽셀 검증으로 충족 가능:
  - Tofu glyph 검출: connected component width 분포 분석
  - 색상 다양성: unique 색상 ≥10 (평탄 단색 PNG 차단)
  - Blank ratio: 단일 색상 픽셀 ≤80%
  - PNG byte 크기 ≥10KB (1×1 placeholder 차단)
- pytesseract import는 optional — 향후 설치되면 자동 OCR 보강

**대안과 기각**:
- (A) tesseract 설치 시도 → **불가**: sudo 비번 미보유 (회장님께 escalate 필요)
- (B) 검증 SKIP → **기각**: task 명시 "silent pass 차단" 위반
- (C) 픽셀 기반 강화 → **채택**: 회장 의도(시각 검증)와 일치, 1차 corruption 100% 검출 가능

### 핵심 결정 3: 25 PNG stratified 샘플링 = 5 카테고리 × 5 패턴 (사이즈는 패턴별 분배)

**근거**:
- task 명시: 카테고리별 5장(보험/SaaS/소비자/럭셔리/기술) × 패턴별 5장(H1~H5) × 사이즈별 5장 = 75 → 25로 stratified
- Latin square 분배: 각 (카테고리, 패턴) 쌍에 사이즈 1개 할당 → 25 unique 조합
- 모든 25장이 verify_korean.py PASS = silent corruption 0 입증

## 3 Step Why 자문

- **1st Why** (왜 이 설계가 필요한가?): 1차에 silent Pillow fallback이 한글 깨진 PNG를 생성하고도 pytest가 PASS 처리한 silent corruption을 영구 차단하기 위함.
- **2nd Why** (왜 이 접근이 최선인가?): hybrid-image 변경 금지 제약 하에서 새 진입점 분리는 회귀 0, 책임 분리, 향후 마이그레이션 점진적 가능. Pillow fallback 제거 + pixel 검증 강화는 tesseract 미설치 환경에서도 silent pass 100% 차단.
- **3rd Why** (왜 이 대안이 다른 대안보다 나은가?): 직접 hybrid-image 수정은 task 위반 + 머지 충돌 위험. tools/ 수정은 권한 외. SKIP 검증은 회장 명시 "다 제대로 해야지" 위반. 새 모듈 + pixel 검증은 모든 제약을 동시 충족하면서 진단 능력은 OCR보다 정밀(tofu width 분석은 OCR보다 정확).

## 참조 자료

- 1차 silent corruption PNG: `/home/jay/workspace/memory/reports/task-2389-evidence/l1_smoke_supabase_h4.png`
- 1차 hybrid-image _satori.py (Pillow fallback 위치): `/home/jay/workspace/skills/hybrid-image/patterns/_satori.py:131-156`
- 정상 동작하는 Node.js Satori: `/home/jay/workspace/tools/ai-image-gen/satori-test/satori_cli.js:53-83`
- 폰트 위치: `/home/jay/.local/share/fonts/Pretendard-{Regular,Bold,SemiBold,Black}.otf`, `/home/jay/.local/share/fonts/NotoSansCJKKR{,-Bold}.otf`, `/home/jay/workspace/tools/ai-image-gen/satori-test/fonts/NotoSansCJKkr-{Regular,Bold}.otf`
- 회장 메모리: `feedback_cardnews_dq_mandatory.md`, `feedback_verification_scenarios.md`

## 주의사항

- **Silent Pillow fallback 제거 필수**: hybrid-image의 _satori.py도 deprecated 안내 (코드는 무수정 — 변경 금지). satori-cardnews._satori는 fallback 0건.
- **mypy/pyright 0**: 새 코드는 strict typing 적용
- **회귀 0**: hybrid-image, magazine-ppt-ko, motion-cardnews-ko, mobile-prototype-ko, frontend-design, insane-design, ids-router, resources/design-md, dispatch.py 등 일체 무변경
- **외부 API 0**: Node.js subprocess 외 외부 호출 금지 (IDS §0.5)
- **L1 PNG 25장 전수 검증**: 1장이라도 verify_korean FAIL 시 .done 금지

## Codex 사전 검증 위험 대응 (2026-05-03)

Codex가 critical 1건 + high 2건 + medium 2건 지적. 각 대응:

### CRITICAL: 호출 경로 단절 위험
**위험**: 새 `skills/satori-cardnews/_satori.py`만 만들면 기존 `skills/hybrid-image/patterns/_satori.py`의 silent fallback이 그대로 살아 있어 task-2389 회귀를 못 막음.

**대응**: 새 모듈에 `install_silent_fallback_guard()` 함수 추가 — import-time monkey-patch로 `skills.hybrid_image.patterns._satori._pillow_fallback`과 `._write_blank_png`을 `RuntimeError("silent fallback blocked by satori-cardnews guard")`로 래핑. 이렇게 하면 hybrid-image 파일 자체는 무수정(변경 금지 준수)이지만 런타임에 silent fallback이 효과적으로 차단됨.

또한 `skills/satori-cardnews/__init__.py` import 시 자동 install을 옵션 제공 (env var `SATORI_CARDNEWS_GUARD=1`). 신규 호출자는 안전한 entry point 사용 권장.

### HIGH: OCR 게이트 환경 의존성
**대응**: `verify_korean.py`에서 `pytesseract` import를 optional로 처리하되, 미설치 시 "PIXEL-ONLY 모드" 메시지를 stdout/return value에 명시 → silent하지 않음. 픽셀 검증은 항상 필수 (tofu glyph 검출, 색상 다양성, blank ratio, PNG 크기). OCR은 가용 시 추가 검증 강도.

### HIGH: task 파일 영향 파일 표기
**대응**: task-2401.md는 회장 발행 문서로 수정 금지. plan.md / context-notes.md / 보고서에 정확한 affected_files 명시.

### MEDIUM: 기존 dev6 약한 게이트 잔존
**대응**: 신규 `tests/design-team/test_ids_phase1_korean_font_embed.py`에서 silent fallback guard install 검증 + 25 PNG 전수 검증으로 강화. 기존 `tests/dev6/test_ids_phase1_korean_ocr.py`는 무수정(회귀 0) 하되, 보고서에 "guard install 시 자동 강화" 명시.

### MEDIUM: 산출물 경로 명세
**대응**: 모두 `task-2401` 경로로 통일 (이미 적용됨).
