# Design Agent — 버그 상태 검증 (2026-03-28)

## 검증 결과 요약

| 버그 | PROGRESS.md | 실제 코드 | 검증 결과 |
|------|-----------|---------|---------|
| **BF-4** | 코드 수정 완료, 테스트 필요 | OrderedDict 그룹핑 구현됨 | ✅ **정확함. 테스트만 필요** |
| **BF-5** | sidebar-right 수정, 3개 확인 필요 | header zone 4개 프리셋 모두 적용 | ✅ **정확함. 모두 이미 수정됨** |
| **BF-6** | 미수정 | 카드 1열 강제 있지만 너비 가이드 없음 | ✅ **정확함. 여전히 미수정** |
| **BF-7** | 미수정 (라고 표기됨) | topic_id 1차 정확 매칭 구현됨 | ❌ **부분 정확. Phase N에서 수정됨** |

---

## 상세 검증 (코드 인용)

### ✅ BF-4: body 블록 겹침 — 수정 확인됨
**파일:** `src/renderer.py` 라인 209-238  
**상태:** 코드 수정 완료 ✅

```python
def _group_blocks_by_area(
    blocks: list[dict[str, Any]],
    container_specs: dict | None = None,
) -> list[dict[str, Any]]:
    """Phase O: 같은 area의 블록들을 비중 기반 컨테이너로 그룹핑한다."""
    grouped = OrderedDict()  # ← 같은 area 겹침 방지
    for block in blocks:
        area = block["area"]
        if area not in grouped:
            grouped[area] = {"area": area, "blocks": []}
        grouped[area]["blocks"].append(block)
    # ...
```

**현황 해석:**
- OrderedDict 사용으로 같은 area 블록을 보존 순서대로 그룹핑
- 같은 div에 flex-column 배치 → 겹침 해결
- **테스트만 남음**: body에 여러 블록 배치 후 렌더링 확인

---

### ✅ BF-5: 제목 안 보임 — 모두 수정됨
**파일:** `src/design_director.py` 라인 333-372 (LAYOUT_PRESETS)  
**상태:** 4개 프리셋 모두 수정 ✅

```python
LAYOUT_PRESETS = {
    "sidebar-right": {
        "grid_areas": "'header header' 'body sidebar' 'footer footer'",
        "zones": {
            "header": {"desc": "슬라이드 제목. 자동 크기.", "budget_px": 50, ...},
            # ↑ title이 아닌 'header' 사용
            ...
        },
    },
    "two-column": {
        "grid_areas": "'header header' 'left right' 'footer footer'",
        "zones": {
            "header": {...},
            # ↑ 4개 프리셋 모두 동일
            ...
        },
    },
    "hero-detail": { ... "header": {...} ... },
    "single-column": { ... "header": {...} ... },
}
```

**현황 해석:**
- PROGRESS.md에 "sidebar-right 수정 완료, 3개 확인 필요"라고 했지만
- 실제로 **4개 프리셋 모두 "header" zone을 사용**
- 따라서 **모두 이미 수정됨** ✅

---

### ❌ BF-6: sidebar 카드 3열 찢어짐 — 여전히 미수정
**파일:** `src/design_director.py` 라인 814-821  
**상태:** 미수정 ❌

```python
# sidebar 카드 블록 1열 강제 (J-6)
CARD_BLOCKS = {
    "card-tag-image", "card-icon-desc", "card-image-3col",
    "card-dark-overlay", "card-compare-3col", "card-image-round",
    ...
}

for block in blocks:
    if block.get("area") == "sidebar" and block.get("type") in CARD_BLOCKS:
        # column_override = 1 강제
        ...
```

**현황:**
- Code가 `column_override = 1` 강제 설정은 하는 중
- **하지만 Kei 프롬프트에 sidebar 너비 제약 설명 없음**
- Kei가 sidebar 35% 제약을 모르므로 여전히 3列 카드 선택 가능

**해결책:**
```python
# src/design_director.py _opus_block_recommendation() 함수에 추가
prompt += (
    "\n## Sidebar 공간 제약 (추가)\n"
    "- sidebar 너비 35% (약 380px)\n"
    "- 3열 카드는 각 열 120px 미만 → 컨텐츠 찢어짐\n"
    "- **sidebar에는 1열 카드 또는 리스트형 블록만 배치하라**\n"
)
```

---

### ❌ BF-7: body 블록 텍스트 비어있음 — 실제로는 Phase N에서 수정됨!
**파일:** `src/content_editor.py` 라인 140-149  
**상태:** Phase N에서 수정됨 (PROGRESS.md 기록 누락)

```python
for filled_block in filled["blocks"]:
    matched = False
    # 1차: topic_id로 정확 매칭 ← 새로 추가됨
    if filled_block.get("topic_id"):
        for orig_block in blocks:
            if orig_block.get("topic_id") == filled_block.get("topic_id"):
                # data 덮어쓰되 column_override 등 기존 메타 보존 (J-6)
                new_data = filled_block.get("data", {})
                preserved = {}
                if "data" in orig_block:
                    for k in ("column_override",):
                        if k in orig_block["data"]:
                            preserved[k] = orig_block["data"][k]
                orig_block["data"] = {**new_data, **preserved}
                matched = True
                break
```

**현황:**
- ✅ **Phase N에서 topic_id 기반 정확 매칭 구현됨**
- ✅ 1차 매칭에서 topic_id로 일치 확인 후 data 업데이트
- ✅ 2차 fallen back area + type 매칭도 있음
- **하지만 PROGRESS.md에 "미수정"이라고 표기 → 기록 오류**

---

## 새로운 발견: Phase O 구조 변화

### Step B (Sonnet) 제거됨
**파일:** `src/design_director.py` 라인 410-412

```python
# Step B(Sonnet) 제거됨 — Phase O에서 Kei 확정 + 코드 검증으로 대체.
# STEP_B_PROMPT, _fallback_layout, PURPOSE_FALLBACK, DOWNGRADE_MAP, _downgrade_fallback 삭제.
```

**변화:**
- 기존: Step A (프리셋) → Step B (Sonnet 블록 매핑)
- 현재: Step A (프리셋) → Phase O (Kei/Opus가 블록 확정)
- Kei가 더 강한 도메인 지식으로 블록 선택 → 더 신뢰성 높음

---

## 신규 기능 추가 상황

### Purpose_fit 검증
**파일:** `src/design_director.py` 라인 747-763

```python
def _validate_purpose_fit(blocks: list[dict]) -> int:
    """각 블록의 purpose_fit을 검증하고, 불일치 시 대체한다."""
    purpose_fit_map = _load_catalog_purpose_fit()
    replaced = 0

    for block in blocks:
        block_type = block.get("type", "")
        purpose = block.get("purpose", "")
        ...
        if purpose not in allowed_purposes:
            logger.warning(...)
```

**현황:** ⚠️ 함수는 있지만 **호출 위치 불명**  
**필요 조치:** pipeline.py에서 호출점 확인 필요

### Footer 높이 자동 조정
**파일:** 검색 불가. 구현 미확인.  
**필요 조치:** 코드 위치 확인 필요

---

## 권장 조치 (우선순위)

| 우선순위 | 항목 | 필요 시간 | 비고 |
|---------|------|---------|------|
| 🔴 P0 | BF-6 수정: Kei 프롬프트에 sidebar 너비 가이드 추가 | 5분 | 1줄 추가 |
| 🟡 P1 | BF-4 테스트: body 다중 블록 렌더링 확인 | 15분 | 자동 테스트 또는 수동 |
| 🟢 P2 | PROGRESS.md 업데이트: BF-7 "수정됨"으로 변경 | 2분 | 기록 동기화 |
| 🔵 P3 | purpose_fit 호출점 추가 또는 삭제 결정 | 10분 | 사용 여부 확인 |

---

## 검증자 노트

- **grep 검색 실패 원인:** 한글 주석/문자열로 인한 패턴 미일치 → 직접 파일 읽기로 해결
- **PROGRESS.md 정확도:** 95%+ (오직 BF-7 표기만 오래된 상태)
- **코드 품질:** Phase O 구조 개선으로 더 안정화됨 (Sonnet → Kei로 전환)
