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

## SCQA

**S**: FiveStagePipeline과 ContentGeneratorV2 두 경로로 카드뉴스를 생성하고 있으며, ContentGeneratorV2에는 `_validate_structure()`로 빈 description/value를 거부하는 검증이 존재한다.

**C**: FiveStagePipeline의 `_build_result()`에는 구조 검증이 전혀 없어, 빈 description/value를 가진 불량 슬라이드가 그대로 렌더링·업로드되는 문제가 발생했다.

**Q**: FiveStagePipeline에도 동일 수준의 구조 검증을 추가하여 불량 카드뉴스 생성을 방지할 수 있는가?

**A**: `_validate_cardnews_slides()` 헬퍼 메서드를 FiveStagePipeline에 추가하고, `_build_result()` cardnews 분기의 return 직전에 호출하도록 구현 완료. TDD로 14개 테스트 작성·통과, pyright 에러 0건. 풀 파이프라인 재실행 후 Threads 업로드 성공 (post_id: 17989307801945120).

## 작업 내역

### Phase 1: 구조 수정
- `_validate_cardnews_slides(self, slides: list[dict]) -> None` 메서드 추가
  - 슬라이드 수 5~7장 검증
  - 첫 슬라이드 cover, 마지막 cta 검증
  - 중간 슬라이드별 검증: card_list(title/label + description), detail(label + value), body(title + description)
  - 검증 실패 시 ValueError raise (슬라이드/아이템 위치 포함)
- `_build_result()` cardnews 분기에서 return 직전에 `self._validate_cardnews_slides(slides)` 호출 추가

### Phase 2: 카드뉴스 재생성 + 업로드
- 토픽: eg-179 (고령화 사회와 연금보험 수요 증가)
- 슬라이드 5장 생성: cover + card_list x2 + detail + cta
- 렌더링: NavyGold 테마, 5장 이미지 생성
- Threads 업로드: 성공 (post_id: 17989307801945120)
- 렌더링 이미지에서 모든 description/value 텍스트가 정상 표시 확인

## 생성/수정 파일 목록
- `/home/jay/projects/ThreadAuto/content/five_stage_pipeline.py` — `_validate_cardnews_slides()` 메서드 추가, `_build_result()`에 호출 추가
- `/home/jay/projects/ThreadAuto/tests/test_five_stage_pipeline.py` — `TestValidateCardnewsSlides` 클래스 14개 테스트 추가, `MOCK_WRITING_CARDNEWS_OUTPUT` mock 데이터 보완 (3장→5장), 기존 테스트 기대값 2건 수정 (MAX_FULL_RETRIES 1→2, timeout 120→600)

## 테스트 결과
- `TestValidateCardnewsSlides`: 14/14 passed (0.06s)
- `test_five_stage_pipeline.py` 전체: 99/99 passed (0.24s)
- 전체 테스트 스위트: 456 passed, 1 failed (test_fact_db_contains_business_page — 본 작업 범위 외)
- pyright: 0 errors, 0 warnings, 0 informations
- black + isort: 적용 완료

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **MOCK_WRITING_CARDNEWS_OUTPUT 3장만 포함** — 신규 검증 추가로 기존 테스트 2건 실패. mock 데이터에 detail/body 슬라이드 2장을 추가하여 유효한 5장으로 보완
   - 상세: `tests/test_five_stage_pipeline.py` MOCK_WRITING_CARDNEWS_OUTPUT slides 배열에 detail(label+value 포함)과 body(title+description 포함) 슬라이드 삽입
2. **card_list item에서 title 대신 label 사용 가능성** — ContentGeneratorV2 검증 기준에 따라 title 또는 label 모두 허용하도록 구현. 전용 테스트 `test_card_list_label_alias_accepted` 추가
3. **detail 슬라이드에서 label/value 항목만 3개인 경우 TIP 렌더링 공간 부족** — 기존 renderer 로직의 정상 동작 (FB-2 로그: "TIP 생략: 남은 공간 80px < 100px"), 수정 불필요 확인

### 자체 해결 추가 (2건)
4. **test_max_retries_constants 기대값 불일치** — 이전 작업에서 `MAX_FULL_RETRIES`가 1→2로 변경되었으나 테스트 기대값이 갱신되지 않음. 테스트 기대값을 현재 코드값(2)으로 수정
5. **test_call_claude_timeout 기대값 불일치** — 이전 작업에서 timeout이 120→600으로 변경되었으나 테스트 기대값이 갱신되지 않음. 테스트 기대값을 현재 코드값(600)으로 수정

### 범위 외 미해결 (1건)
1. **test_fact_db_contains_business_page 실패** — fact_db.md에 '사업단 페이지' 표기 부재. 범위 외 사유: 데이터 콘텐츠 이슈, 본 작업과 무관

## 검증 포인트 결과
- 생성된 slides의 각 item에 description/value 텍스트 존재: 렌더링 이미지에서 모든 글박스 내 설명 텍스트 확인
- 렌더링 이미지 경로 (5장):
  - `/home/jay/projects/ThreadAuto/output/cardnews_20260318_223529_00.png` ~ `_04.png`
- Threads 업로드 성공: post_id 17989307801945120

## QC 자동 검증
- **overall**: WARN (Gate PASS)
- file_check: PASS (22,108 bytes / 82,395 bytes)
- data_integrity: PASS
- test_runner: PASS (99 passed in 0.16s)
- tdd_check: PASS
- pyright_check: WARN (8건 — 모두 기존 import resolution 이슈, 본 작업과 무관)
- style_check: PASS (black + isort OK)
- .done 파일 자동 생성 완료
