# task-697.1 완료 보고서

## SCQA

**S**: ThreadAuto 카드뉴스 렌더러가 cover + 콘텐츠 3~5장 + CTA 구조로 슬라이드를 생성하고 있으며, card_list/detail 2종 렌더러가 동작 중이다.

**C**: card_list 렌더러(_01, _02)가 bottom-align으로 카드를 배치하여 상단에 과도한 빈 공간이 생기고, TIP 박스는 고정 높이(130px)로 내용 대비 하단 여백이 과다하며, 일부 슬라이드에서 subtitle이 누락되어 디자인 일관성이 깨져있다.

**Q**: _01~_03 슬라이드 레이아웃을 _03 기준으로 통일하고, TIP 박스 여백을 자연스럽게 줄이며, subtitle 출력을 필수로 강제할 수 있는가?

**A**: 3가지 수정을 모두 완료했다. (1) card_list를 bottom-align에서 top-align으로 변경하여 제목 바로 아래에서 카드가 시작되도록 통일, (2) TIP 박스 높이를 텍스트 줄 수 기반 동적 계산(80~160px 범위)으로 변경, (3) prompts_v2.py에 subtitle 필수 규칙 추가. pyright 에러 0건, 렌더링 테스트 3장 모두 정상 생성.

## 수정 파일

### 1. `/home/jay/projects/ThreadAuto/renderer/cardnews.py`

**render_card_list() — 상단 정렬 변경** (line 1220~1222)
- Before: Bottom-align 로직 8줄 (`available_bottom`, `content_start_y` 역산)
- After: Top-align 3줄 (`cur_card_y = cards_top`)
- 효과: 제목 영역 바로 아래에서 카드 시작. 상단 빈 공간 제거.

**render_detail() — TIP 박스 동적 높이** (line 1429~1445)
- Before: `tip_h = 130` (고정)
- After: 텍스트를 미리 wrap → 줄 수 * line_height + 패딩 40px → `max(80, min(160, 계산값))`
- 추가: line 1606에서 `min(160, remaining_space)` → `min(tip_h, remaining_space)`로 변경
- 효과: 짧은 TIP 텍스트 시 박스가 컴팩트해짐.

### 2. `/home/jay/projects/ThreadAuto/content/prompts_v2.py`

**subtitle 필수 규칙 추가**
- line 71: `"subtitle": "보조 설명 (선택)"` → `"subtitle": "보조 설명 (필수, 15자 이내)"`
- line 81: `"subtitle": ""` → `"subtitle": "보조 설명 (필수, 15자 이내)"`
- line 134-135: 슬라이드 구성 규칙에 2줄 추가 (subtitle 필수 + 15자 이내)

## 검증 결과

- **pyright**: 에러 0건, 경고 0건
- **black + isort**: 2 files unchanged (이미 준수)
- **렌더링 테스트**: 3장 생성 성공
  - task697_01.png: card_list 2 items + subtitle → 상단 정렬 확인
  - task697_02.png: card_list 2 items + subtitle → 상단 정렬 + 부제목 표시 확인
  - task697_03.png: detail 3 items + TIP + subtitle → TIP 박스 컴팩트 + 부제목 표시 확인
- **Before/After 비교**: _01, _02에서 상단 빈 공간 완전 제거. _03에서 TIP 박스 높이 감소 확인.

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **card_list bottom-align으로 인한 상단 빈 공간** — `available_bottom` 역산 로직 제거, `cards_top` 직접 할당으로 top-align 전환
2. **TIP 박스 고정 높이(130px)로 인한 과도한 하단 여백** — `wrap_text()` 사전 계산으로 동적 높이 산출 (line_h=40px, padding=40px, range 80~160px)
3. **prompts_v2.py의 detail 예시에서 subtitle이 빈 문자열("")** — 예시를 "보조 설명 (필수, 15자 이내)"로 변경하여 LLM이 빈 값을 학습하지 않도록 방지

### 범위 외 미해결 (1건)
1. **detail 렌더러도 bottom-align 코드가 존재** — 현재 3 items + TIP 구성에서는 문제 없지만, 2 items만 있는 경우 동일 현상 가능. 범위 외 사유: 작업 지시가 card_list만 명시했으며, detail은 _03 기준으로 이미 양호.

## QC 자동 검증

```
overall: WARN (Gate PASS)
- file_check: PASS (cardnews.py 96283B, prompts_v2.py 18938B)
- data_integrity: PASS
- style_check: PASS (black OK, isort OK)
- critical_gap: PASS
- pyright_check: WARN (기존 패키지 import 2건 - renderer.engine, renderer.themes - 본 작업 무관)
- tdd_check: SKIP (파일명 패턴 불일치. pytest 직접 실행으로 89건 전체 통과 확인)
- test_runner: MANUAL_SKIP (동일 사유. pytest tests/test_cardnews_renderer.py → 89 passed in 20.76s)
```

## 산출물
- 수정된 `cardnews.py` diff: card_list top-align + TIP 동적 높이
- 수정된 `prompts_v2.py` diff: subtitle 필수 규칙
- 렌더링 이미지 3장: sendfile 전송 완료
