# Task: ThreadAuto 콘텐츠 자동생성 — Phase 2: LLM 콘텐츠 생성 엔진

## Task ID: task-274.2
## 프로젝트 경로: /home/jay/projects/ThreadAuto/

## 선행 Phase 산출물 (Phase 1에서 생성됨)
- `content/evergreen_topics.json` — 에버그린 주제풀 200개
- `content/topic_selector.py` — 소재 선택 엔진
- `crawler/rss_crawler.py` — RSS 크롤러
- `crawler/youtube_crawler.py` — 유튜브 자막 크롤러
- `content/fact_db.md` — 팩트 DB (이미 존재)

## 목표
소재 선택 엔진이 뽑은 10개 주제를 **Claude CLI**로 카드뉴스 텍스트를 생성하고, **금감원 규정 필터**를 적용하는 엔진을 만든다.

## 작업 범위

### 1. LLM 콘텐츠 생성 엔진
- 파일: `content/content_generator_v2.py` (기존 generator.py 유지, 신규 생성)
- Claude CLI 호출: `claude --print --model claude-sonnet-4-6 --system-prompt "..." < input`
  - 반드시 `unset CLAUDECODE` 환경변수 필요 (nested session 방지)
  - `--max-tokens` 플래그 사용 금지 (지원 안 됨)
- 입력: topic_selector.py가 선택한 10개 소재
- 출력: 각 소재별 카드뉴스 슬라이드 텍스트 (7장 구성)
  ```json
  {
    "topic_id": "eg-001",
    "category": "고민공감",
    "card_type": "E",
    "slides": [
      {"type": "cover", "hook": "훅 문구", "title": "메인 타이틀"},
      {"type": "body", "number": 1, "title": "소제목", "description": "상세 설명"},
      {"type": "body", "number": 2, "title": "소제목", "description": "상세 설명"},
      ...
      {"type": "cta", "text": "CTA 문구", "contact": "DM/블로그 안내"}
    ],
    "caption": "Threads 텍스트 캡션 (500자 이내)",
    "hashtags": ["보험설계사", "이직", ...]
  }
  ```

### 2. 시스템 프롬프트 설계
- 파일: `content/prompts_v2.py`
- 페르소나: "서울대보험쌤" — 전문적이되 친근, 데이터 기반, 과장 배제
- fact_db.md 내용을 시스템 프롬프트에 주입
- 카테고리별 톤 차이:
  - 고민공감: 공감 → 해결 방향 제시 (부드럽게)
  - 정보제공: 팩트 기반, 교육적, 전문성 과시
  - 사회적증거: 이야기체, 감성적, 신뢰 구축
  - 업계동향: 뉴스 인용 + 독자적 해석 (타인 공격 금지, 금소법 준수)
  - CTA: 부담 없는 문의 유도, 강압 금지
- 업계동향형은 RSS/유튜브에서 가져온 원문을 컨텍스트로 주입하고, "독자적 시각으로 재해석"하도록 지시
- 금지사항을 프롬프트에 명시:
  - fact_db.md에 없는 수치/통계 생성 금지
  - 특정 타사 보험회사명 언급 금지
  - 수익률/보장액 확정적 표현 금지
  - 긴급/압박 유도 금지
  - 원금보장, 무조건 지급 표현 금지

### 3. 금감원 규정 필터 (3단)
- 파일: `content/compliance_filter.py`

**Layer 1 — 키워드 블랙리스트** (정규식)
```python
BLACKLIST_PATTERNS = [
    r"(연|월)\s*\d+(\.\d+)?%\s*(보장|확정|약속)",
    r"무조건\s*(보장|지급|수령)",
    r"원금\s*보장",
    r"(오늘|지금|이번\s*달).*마감",
    r"한정\s*(수량|기간)",
    r"(삼성|한화|교보|현대|DB|메리츠|흥국)\s*(생명|화재|보험)보다",
    r"타사\s*(대비|보다)\s*(저렴|유리|좋)",
]
```

**Layer 2 — 수치 탐지 + 팩트 DB 교차검증**
- 생성된 텍스트에서 수치(%, 원, 배, 명) 추출
- fact_db.md에 해당 수치가 존재하는지 확인
- 없는 수치 → 해당 문장 자동 제거 또는 전체 콘텐츠 폐기

**Layer 3 — 스코어링**
```python
def compliance_check(text: str) -> dict:
    """
    Returns: {"pass": bool, "flags": list[str], "risk_level": "low|medium|high"}
    - low: 자동 발행 가능
    - medium: 수치 제거 후 자동 발행
    - high: 폐기, 예비 콘텐츠로 대체
    """
```

### 4. 전체 생성 파이프라인
- 파일: `content/pipeline.py`
- 흐름:
  1. `topic_selector.select_daily(10)` → 10개 소재
  2. `rss_crawler.fetch()` → 최신 뉴스 (업계동향용)
  3. `youtube_crawler.fetch_latest()` → 최신 유튜브 (업계동향용)
  4. 각 소재별 `content_generator_v2.generate(topic, context)` → 카드뉴스 텍스트
  5. `compliance_filter.check(text)` → 필터 통과/폐기
  6. 통과된 콘텐츠 저장: `content/daily_queue/YYYY-MM-DD.json`
- CLI 실행: `python3 -m content.pipeline` 으로 독립 실행 가능

## 기술 참고
- Claude CLI 경로: `claude` (PATH에 있음)
- `unset CLAUDECODE` 필수
- 호출 예: `subprocess.run(["claude", "--print", "--model", "claude-sonnet-4-6", "--system-prompt", system], input=user_msg, capture_output=True, text=True, env=env)`
- env에서 CLAUDECODE 키 제거해야 함

## 테스트
- `tests/test_content_generator_v2.py` — LLM 출력 구조 검증 (mock CLI)
- `tests/test_compliance_filter.py` — 3단 필터 테스트
- `tests/test_pipeline.py` — 전체 파이프라인 통합 테스트 (mock)
- 기존 테스트 깨지면 안 됨

## 산출물
- `content/content_generator_v2.py`
- `content/prompts_v2.py`
- `content/compliance_filter.py`
- `content/pipeline.py`
- 테스트 파일들
- 완료 시 `memory/events/task-274.2.done` 생성
- 보고서 `memory/reports/task-274.2.md` 작성