문서 정리: Phase 히스토리 md를 docs/history/로 이동 + 오래된 테스트/에셋 정리
- 루트의 IMPROVEMENT-PHASE-*.md, PHASE-*.md 등 45개 → docs/history/로 이동 - docs/block-tests/ 오래된 블록 테스트 HTML 삭제 (figma_to_html_agent로 대체) - docs/figma-analysis/, docs/figma-assets/, docs/figma-screenshots/ 정리 - docs/test-*.html 등 초기 테스트 파일 정리 - 참고 페이지/ 스크린샷 정리 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
317
docs/history/PHASE-V.md
Normal file
317
docs/history/PHASE-V.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# Phase V (Verification) — 콘텐츠-컨테이너 적합성 검증 + Kei 에스컬레이션
|
||||
|
||||
> 작성일: 2026-04-02
|
||||
> 근거: Phase T' 디버깅 과정에서 발견된 파이프라인 구조적 결함
|
||||
> 선행: Phase T (파이프라인 구조), Phase T' (시각 품질)
|
||||
|
||||
---
|
||||
|
||||
## 배경
|
||||
|
||||
### 발견된 구조적 문제
|
||||
|
||||
Phase T' 디버깅 중 step-by-step 시각 검토를 진행하면서 다음이 드러남:
|
||||
|
||||
1. **컨테이너 크기가 콘텐츠 분량과 무관하게 결정됨**
|
||||
- Stage 1.5a에서 weight(0.6, 0.2, 0.1, 0.1) 고정 배분
|
||||
- 배경에 꼭지 2개(220자)가 배정되었으나 117px밖에 안 됨 → 넘침
|
||||
- 본심은 345px인데 실제 필요 260px → 85px 남음
|
||||
|
||||
2. **"들어가는지" 검증 단계가 없음**
|
||||
- 블록 선택(Stage 1.7) 후 바로 HTML 생성(Stage 2)으로 넘어감
|
||||
- 콘텐츠가 컨테이너에 실제로 들어가는지 아무도 확인하지 않음
|
||||
- Sonnet이 넘치는 내용을 받아서 overflow/스크롤/잘림 발생
|
||||
|
||||
3. **안 될 때 판단하는 주체가 없음**
|
||||
- 공간 부족 시 옵션(합치기, 축약, 팝업 이동, 구조 변경)을 생성하고
|
||||
- Kei 페르소나에게 결정을 요청하는 프로세스가 없음
|
||||
- 현재는 그냥 Sonnet에게 "넣어라"만 함
|
||||
|
||||
4. **영역당 블록 1개만 선택됨**
|
||||
- 배경에 꼭지 2개가 있어도 블록 1개(callout-warning)만 선택
|
||||
- 1꼭지 = 1블록 원칙이 지켜지지 않음
|
||||
|
||||
---
|
||||
|
||||
## 절대 원칙
|
||||
|
||||
1. **하드코딩 금지** — font-size 외 모든 수치는 동적 계산. 어떤 MDX가 들어와도 동일하게 동작
|
||||
2. **스크롤 절대 금지** — overflow:auto/scroll 어떤 영역에서도 불허
|
||||
3. **1꼭지 = 1블록** — 컨테이너에 꼭지 N개면 블록 N개가 개별 선택
|
||||
4. **콘텐츠 분량 → 컨테이너 크기** — weight 고정이 아니라 콘텐츠 필요 높이 기반 배분
|
||||
5. **AI가 옵션 생성, Kei가 결정** — 안 될 때 하드코딩 대응이 아니라 Kei 판단 요청
|
||||
|
||||
---
|
||||
|
||||
## 개선된 파이프라인
|
||||
|
||||
```
|
||||
기존:
|
||||
1A → 1B → 1.5a(weight고정) → 1.5b → 1.7(영역당1블록) → 2(HTML) → 3 → 4
|
||||
↑
|
||||
여기서 넘치거나 잘림
|
||||
|
||||
개선:
|
||||
1A → 1B → 1.7(꼭지별1블록) → 1.8★(적합성검증) → 2(HTML) → 3 → 4
|
||||
│
|
||||
├ 필요 높이 계산
|
||||
├ 컨테이너 재배분
|
||||
└ 안 되면 → Kei 에스컬레이션
|
||||
```
|
||||
|
||||
### 변경 사항 요약
|
||||
|
||||
| Stage | 기존 | 개선 |
|
||||
|-------|------|------|
|
||||
| 1.5a | weight 고정 배분 | 삭제 — 1.8에서 콘텐츠 기반 계산 |
|
||||
| 1.7 | 영역당 블록 1개 | **꼭지당 블록 1개** |
|
||||
| **1.8 (신규)** | 없음 | **적합성 검증 + 재배분 + Kei 에스컬레이션** |
|
||||
|
||||
---
|
||||
|
||||
## Stage 1.8: 적합성 검증 (신규)
|
||||
|
||||
### 입력
|
||||
|
||||
- 꼭지 목록 + 영역 배정 (Stage 1A/1B)
|
||||
- 꼭지별 선택된 블록 + 블록 최소 높이 (Stage 1.7)
|
||||
- 슬라이드 크기 (1280×720), padding, gap 등 고정 스펙
|
||||
|
||||
### 처리 흐름 (AI가 자동 — 하드코딩 아님)
|
||||
|
||||
```
|
||||
Step 1: 필요 높이 계산
|
||||
각 컨테이너별로:
|
||||
- 배정된 꼭지들의 텍스트 분량(자수) 파악
|
||||
- 해당 영역 font-size + line-height로 필요 줄 수 계산
|
||||
- 선택된 블록의 padding, 제목, 마진 등 오버헤드 합산
|
||||
- → 필요 최소 높이(px) 산출
|
||||
|
||||
Step 2: 슬라이드 공간 배분
|
||||
720px 에서:
|
||||
- header(고정) + footer(고정) + gap 빼기
|
||||
- 남은 공간을 각 영역의 필요 높이 비율로 배분
|
||||
- sidebar는 body와 같은 row이므로 sidebar 높이 = body 영역 합계
|
||||
|
||||
Step 3: 적합성 검증
|
||||
각 컨테이너별로:
|
||||
- 배분된 높이 ≥ 필요 높이 → 통과
|
||||
- 배분된 높이 < 필요 높이 → Step 4로
|
||||
|
||||
Step 4: 재배분 시도
|
||||
여유 있는 영역에서 부족한 영역으로 공간 이동:
|
||||
- 각 영역의 (배분 높이 - 필요 높이) = 여유분 계산
|
||||
- 여유분 > 0인 영역에서 부족 영역으로 재분배
|
||||
- 재배분 후 모든 영역이 필요 높이 이상 → 통과
|
||||
- 아직 부족 → Step 5로
|
||||
|
||||
Step 5: Kei 에스컬레이션
|
||||
AI가 현황 + 시도 결과 + 옵션을 정리하여 Kei에게 요청:
|
||||
|
||||
[현황]
|
||||
- 어떤 영역이 몇 px 부족한지
|
||||
- 어떤 영역에 여유가 있는지
|
||||
|
||||
[시도 결과]
|
||||
- 재배분으로 해결 가능한지/불가능한지
|
||||
- 해결 가능하면 어떤 영역에서 얼마를 가져오는지
|
||||
|
||||
[옵션]
|
||||
A. 꼭지 합치기 — 여러 꼭지를 하나의 블록 안에서 흐름으로 연결
|
||||
B. 인라인 축약 — 사례 등을 괄호 한 줄로 축약
|
||||
C. 팝업 이동 — 상세 내용을 팝업으로 빼고 링크만 남김
|
||||
D. 컨테이너 재조정 — 다른 영역에서 공간을 가져옴
|
||||
E. 그리드 구조 변경 — 배경 전체폭 등 레이아웃 자체 변경
|
||||
F. 기타 (Kei 판단)
|
||||
|
||||
[결정 요청]
|
||||
위 옵션 중 선택하거나 다른 방향을 제시해주세요.
|
||||
```
|
||||
|
||||
### Stage 1.8 내부 루프
|
||||
|
||||
```
|
||||
Step 1: 부족/여유 검증 (calculate_fit)
|
||||
Step 2: 재배분 시도 (redistribute)
|
||||
Step 3: 부족 시 → Kei 에스컬레이션 (call_kei_fit_escalation)
|
||||
Step 4: 여유 시 → 보충 콘텐츠 탐색 (analyze_enhancements)
|
||||
├ 관련 팝업에 구조화 콘텐츠(표/비교) 있으면 제안
|
||||
├ 영역 핵심 결론 → 강조 블록 제안
|
||||
└ 텍스트 핵심 키워드 → bold 목록 생성
|
||||
Step 5: Kei 확인 (AI가 제안, Kei가 승인/수정)
|
||||
Step 6: 보충 블록 선택 + fit 재검증
|
||||
├ Kei가 승인한 보충 콘텐츠에 맞는 블록을 catalog에서 선택
|
||||
├ 추가 블록의 높이가 여유 공간에 들어가는지 재검증
|
||||
└ 안 들어가면 축소 (행 수 줄이기) 또는 제외
|
||||
Step 7: 세부 컨테이너 배치 계산
|
||||
├ 메인 컨테이너 안에서 세부 컨테이너 배치 (SVG/텍스트/표/key-msg)
|
||||
├ 각 세부 컨테이너 크기를 콘텐츠에서 동적 계산
|
||||
├ 빈 공간 측정 → 보충 콘텐츠 크기 결정 (표 행 수 등)
|
||||
├ 세부 컨테이너 간 정렬 (좌우 높이 다르면 짧은 쪽 중앙맞춤)
|
||||
└ 최종 overflow 검증
|
||||
Step 8: 확정 출력
|
||||
```
|
||||
|
||||
### 출력
|
||||
|
||||
- 확정된 컨테이너 크기 (재배분 반영)
|
||||
- 각 컨테이너별 꼭지-블록 매핑 (Kei 결정 반영)
|
||||
- 보충 블록 목록 (여유 공간에 추가된 블록)
|
||||
- 강조 블록 목록 (핵심 결론용)
|
||||
- bold 키워드 목록 (Stage 2 프롬프트에 전달)
|
||||
- 콘텐츠 정리 방향 (합치기/축약/팝업 등 — Kei 결정 반영)
|
||||
|
||||
---
|
||||
|
||||
## 태스크 목록
|
||||
|
||||
### V-1: Stage 1.7 수정 — 꼭지별 블록 선택
|
||||
|
||||
- **현재:** `select_reference_block()`이 영역(배경/본심/첨부/결론) 단위로 1개 블록 선택
|
||||
- **변경:** 각 영역 내 꼭지마다 개별적으로 블록 선택
|
||||
- **파일:** `src/block_reference.py`, `src/pipeline.py` (Stage 1.7 호출부)
|
||||
- **완료 기준:** 배경에 꼭지 2개 → 블록 2개 선택. 꼭지 1개면 블록 1개.
|
||||
|
||||
### V-2: Stage 1.8 신규 구현 — 적합성 검증
|
||||
|
||||
- **파일:** `src/fit_verifier.py` (신규)
|
||||
- **내용:**
|
||||
- Step 1~3: 필요 높이 계산 + 공간 배분 + 적합성 검증
|
||||
- 모든 계산은 동적 (font-size, line-height, 블록 padding 등에서 도출)
|
||||
- **완료 기준:** 배경 117px → 부족 감지 → 재배분 시도
|
||||
|
||||
### V-3: Stage 1.8 재배분 로직
|
||||
|
||||
- **파일:** `src/fit_verifier.py`
|
||||
- **내용:**
|
||||
- Step 4: 여유 영역 → 부족 영역으로 공간 재분배
|
||||
- 재배분 후 결과를 Stage 2에 전달
|
||||
- **완료 기준:** 배경 117→151px, 본심 345→311px 자동 재배분
|
||||
|
||||
### V-4: Stage 1.8 Kei 에스컬레이션
|
||||
|
||||
- **파일:** `src/fit_verifier.py`, `src/kei_client.py`
|
||||
- **내용:**
|
||||
- Step 5: 재배분으로도 안 될 때 옵션 생성 + Kei API 호출
|
||||
- Kei 응답 파싱 → 결정에 따라 컨테이너/콘텐츠 조정
|
||||
- **의존성:** V-2, V-3
|
||||
- **완료 기준:** Kei에게 옵션 전달 → Kei 결정 수신 → 파이프라인 계속
|
||||
|
||||
### V-5: Stage 1.5a 리팩터
|
||||
|
||||
- **파일:** `src/space_allocator.py`, `src/pipeline.py`
|
||||
- **내용:**
|
||||
- 기존 weight 고정 배분 로직을 V-2의 콘텐츠 기반 계산으로 교체
|
||||
- 또는 1.5a를 삭제하고 1.8이 컨테이너 계산을 전담
|
||||
- **완료 기준:** weight 하드코딩 제거. 콘텐츠 분량 기반 동적 배분.
|
||||
|
||||
### V-6: 통합 검증 — 완료
|
||||
|
||||
- 전수 하드코딩 스캔: 레이아웃 하드코딩 0개
|
||||
- 통합 테스트: 31/31 통과
|
||||
- step-by-step HTML: step1~step3 생성 + 시각 검토
|
||||
|
||||
---
|
||||
|
||||
## Phase V-2: 콘텐츠 품질 강화 (Step 3 디버깅에서 발견)
|
||||
|
||||
> Step 3 시각 검토에서 발견된 4가지 개선 사항.
|
||||
> 모두 "AI가 분석, Kei가 확인"하는 동일 프로세스.
|
||||
|
||||
### V-7: 주종 관계 블록 내 종속 꼭지 처리
|
||||
|
||||
- **발견:** 배경에 꼭지1(intro)+꼭지2(supporting) → 블록 1개로 합쳤지만, 종속 꼭지를 어떻게 표현할지 미정
|
||||
- **규칙 (동적):**
|
||||
- 종속 꼭지 콘텐츠 분량 확인 (fit_verifier의 텍스트 분량 계산 활용)
|
||||
- 짧으면 (팝업 참조 1~2줄) → 인라인 (주 블록 안에 한 줄)
|
||||
- 길거나 구조 있으면 → 하위 블록 (블록 안의 블록)
|
||||
- 독립성 있으면 → 보조 블록 (나란히)
|
||||
- **판단 기준:** 종속 꼭지의 source_data 길이 + 팝업 참조 여부 + purpose
|
||||
- **Kei 확인:** AI가 "인라인/하위블록/보조블록" 중 제안 → Kei가 확인
|
||||
- **파일:** `src/fit_verifier.py`, `src/block_reference.py`
|
||||
|
||||
### V-8: 여유 공간 콘텐츠 보충
|
||||
|
||||
- **발견:** 본심 컨테이너에 ~53px 여유. 관련 팝업(DX vs BIM 비교표 1135자)이 있는데 활용 안 됨
|
||||
- **규칙 (동적):**
|
||||
- 재배분 후 여유 공간 감지 (shortfall < -threshold)
|
||||
- 해당 영역의 꼭지에 관련 팝업이 있는지 확인 (source_data에 [팝업:] 참조)
|
||||
- 팝업에 구조화 콘텐츠(표, 비교, 목록)가 있으면
|
||||
- 여유 공간에 맞는 블록 추가 선택 (catalog에서)
|
||||
- 팝업 핵심만 요약하여 배치 제안
|
||||
- **Kei 확인:** "53px 여유. 비교표 핵심 3행을 넣을까요?" → Kei가 확인
|
||||
- **파일:** `src/fit_verifier.py`
|
||||
|
||||
### V-9: 영역 핵심 결론 강조 블록
|
||||
|
||||
- **발견:** 배경의 "체계적 정립 필요"가 단순 불릿과 동급. 시각적 강조 없음
|
||||
- **규칙 (동적):**
|
||||
- 각 영역의 꼭지 purpose에서 핵심 결론 추출
|
||||
- purpose=문제제기 → 마지막 문장이 결론적 패턴("~필요", "~해야")이면 강조 블록
|
||||
- purpose=핵심전달 → core_message와 관련된 문장이면 강조 블록
|
||||
- 강조 블록: highlight-strip, callout 내 강조 div 등 catalog에서 선택
|
||||
- **Kei 확인:** "이 문장을 강조 블록으로 처리할까요?" → Kei가 확인
|
||||
- **파일:** `src/fit_verifier.py`, `src/block_reference.py`
|
||||
|
||||
### V-10: 텍스트 핵심 키워드 bold
|
||||
|
||||
- **규칙 (동적):**
|
||||
- source_data에서 핵심 용어 추출 (꼭지 title에 포함된 키워드, **bold** 마크된 텍스트)
|
||||
- 해당 키워드를 HTML 생성 시 bold 처리하도록 Sonnet에게 전달
|
||||
- **파일:** `src/html_generator.py` (Stage 2 프롬프트에 키워드 목록 포함)
|
||||
|
||||
---
|
||||
|
||||
## 의존 관계
|
||||
|
||||
```
|
||||
Phase V-1 (완료):
|
||||
V-1 → V-2 → V-3 → V-4 → V-5 → V-6 ✅
|
||||
|
||||
Phase V-2 (신규):
|
||||
V-7 (종속 꼭지 처리) ← fit_verifier 활용
|
||||
V-8 (여유 공간 보충) ← fit_verifier 확장
|
||||
V-9 (강조 블록) ← purpose 분석
|
||||
V-10 (bold 키워드) ← source_data 분석
|
||||
→ 전체 통합 검증 (step-by-step HTML 재생성)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 하드코딩 전수 점검 결과
|
||||
|
||||
### 반드시 제거 (Phase V에서 동적 계산으로 교체)
|
||||
|
||||
| # | 파일 | 라인 | 값 | 문제 | 교체 방향 |
|
||||
|---|------|------|-----|------|----------|
|
||||
| 1 | `space_allocator.py` | 161 | `474` | body zone 높이 고정 | 슬라이드에서 header+footer+gap 빼고 동적 계산 |
|
||||
| 2 | `space_allocator.py` | 160 | `0.35*0.85` | sidebar 비율+패딩 고정 | container_ratio + 실제 padding에서 계산 |
|
||||
| 3 | `html_generator.py` | 543 | `720-80-66-footer_h-40` | body zone 높이 산술 하드코딩 | containers에서 받은 height_px 사용 |
|
||||
| 4 | `html_generator.py` | 604,921 | `380` | sidebar width fallback | containers에서 받은 width_px 사용 (fallback 제거) |
|
||||
| 5 | `html_generator.py` | 621 | `1200` | footer width fallback | containers에서 받은 width_px 사용 |
|
||||
| 6 | `design_director.py` | 314 | `490` | FRAME_AVAILABLE_HEIGHT 고정 | 슬라이드 스펙에서 동적 계산 |
|
||||
| 7 | `design_director.py` | 328-366 | `budget_px` 다수 | 프리셋별 zone budget 고정 | Stage 1.8에서 콘텐츠 기반 재계산 |
|
||||
| 8 | `space_allocator.py` | 301,583 | `0.85` | 패딩 비율 고정 | `(slide_width - padding*2) / slide_width` 로 계산 |
|
||||
|
||||
### fallback 값 (정상 흐름에서는 도달하면 안 됨)
|
||||
|
||||
| # | 파일 | 라인 | 값 | 비고 |
|
||||
|---|------|------|-----|------|
|
||||
| 9 | `space_allocator.py` | 299 | `490` | zone_budget 기본값 — preset에서 반드시 와야 함 |
|
||||
| 10 | `space_allocator.py` | 304,313 | `0.25` | weight 기본값 — Kei가 반드시 제공해야 함 |
|
||||
| 11 | `pipeline.py` | 960 | `490` | budget_px fallback |
|
||||
|
||||
### 교체 원칙
|
||||
|
||||
- **모든 px 값:** 이전 Stage의 계산 결과(containers, font_hierarchy 등)에서 받아 사용
|
||||
- **비율 값(0.85 등):** 실제 padding/gap에서 역산하여 계산
|
||||
- **fallback:** 정상 흐름에서 절대 도달하지 않도록 이전 Stage에서 반드시 값을 제공
|
||||
- **font-size만 예외:** 디자인 토큰으로 정의된 텍스트 크기는 하드코딩 허용
|
||||
|
||||
---
|
||||
|
||||
## 이전 Phase와의 관계
|
||||
|
||||
- **Phase T:** 파이프라인 Stage 0~5 구조 완성 → Phase V는 Stage 1.7~1.8 개선
|
||||
- **Phase T' (TP-1~6):** 시각 품질 개선 (프롬프트, 후처리) → Phase V 적용 후 재검증 필요
|
||||
- **Phase T' 후처리:** sidebar width:100%, overflow 제거, bold 변환, 폰트 캡 → 유지
|
||||
Reference in New Issue
Block a user