# task-701.1: FiveStagePipeline 슬라이드 구조 검증 + 카드뉴스 재업로드

## 배경
FiveStagePipeline으로 생성된 카드뉴스에서 items의 description/value가 빈 채로 렌더링됨.
ContentGeneratorV2에는 `_validate_structure()`가 있어 빈 description을 거부하지만,
FiveStagePipeline의 `_build_result()`에는 **검증이 전혀 없어** 불량 콘텐츠가 그대로 통과됨.

## Phase 1: 구조 수정

### 수정 대상
- `/home/jay/projects/ThreadAuto/content/five_stage_pipeline.py`
  - `_build_result()` 메서드 (line 149~245)

### 구현 사항
1. `_build_result()`의 cardnews 분기(line 220~)에서 slides를 반환하기 전에 **구조 검증** 추가
2. 검증 로직 (ContentGeneratorV2._validate_structure와 동일 기준):
   - slides가 5~7장인지
   - 첫 슬라이드가 cover, 마지막이 cta인지
   - 중간 슬라이드 각각:
     - card_list: 각 item에 `title`(또는 `label`) AND `description` 비어있지 않은지
     - detail: 각 item에 `label` AND `value` 비어있지 않은지
     - body: `title` AND `description` 비어있지 않은지
3. 검증 실패 시 `ValueError` raise (메시지에 어떤 슬라이드/아이템이 문제인지 포함)
4. 이 ValueError는 FiveStagePipeline.generate()의 기존 재시도 루프에서 catch되어 재시도됨

### 구현 방식
- `_validate_cardnews_slides(slides)` 헬퍼 메서드를 FiveStagePipeline 클래스에 추가
- `_build_result()`에서 return 직전에 호출
- ContentGeneratorV2._validate_structure()를 참고하되 중복 코드 말고 필요한 부분만

### 제약사항
- prompts_v2.py 수정 금지
- renderer/cardnews.py 수정 금지
- content_generator_v2.py 수정 금지
- 기존 테스트 깨뜨리지 말 것

## Phase 2: 카드뉴스 재생성 + 업로드

### 실행
1. 수정 후 기존 테스트 실행: `cd /home/jay/projects/ThreadAuto && python3 -m pytest tests/ -x -q 2>&1 | tail -20`
2. 풀 파이프라인 실행: `cd /home/jay/projects/ThreadAuto && python3 run_full_pipeline.py`
3. 생성된 콘텐츠를 `output/cardnews_content.json`에 저장 (디버깅용)
4. 렌더링된 이미지 경로 보고
5. Threads 업로드 결과 보고

### 검증 포인트
- 생성된 slides의 각 item에 description/value가 40자 이상인지 확인
- 렌더링 이미지에서 글박스 안에 설명 텍스트가 보이는지 확인
- 업로드 성공 여부 (실패 시 에러 메시지 포함)