# Design Agent — 개선 계획 CLAUDE.md 요구사항 전수검토 결과 발견된 미구현/부분구현/위반 사항 33개의 개선 계획. 2026-03-25 기준 코드 감사 결과에 기반. --- ## Phase A: 슬라이드 품질 핵심 (8개) > "프레임에 내용이 안 보인다"의 직접 원인. 최우선. > **실행 상세:** [IMPROVEMENT-PHASE-A.md](IMPROVEMENT-PHASE-A.md) ### A-1: 4단계 Sonnet 디자인 조정 추가 - **현재:** Jinja2 렌더링만 수행. 텍스트 길이에 맞는 디자인 조정 없음. - **CLAUDE.md:** "디자인 실무자 (Sonnet + Jinja2 + CSS) — 편집자가 정리한 텍스트에 맞게 폰트/여백/박스 조정" - **작업:** pipeline.py 4단계에서 render_slide() 호출 전, Sonnet이 블록별 텍스트 길이를 보고 CSS 조정값(font-size, padding, gap 등)을 결정하는 호출 추가 - **파일:** pipeline.py, 새 함수 또는 renderer.py 확장 - **의존성:** 없음 ### A-2: 5단계 HTML을 프롬프트에 전달 - **현재:** `_review_balance(html, ...)` 시그니처에 html 있지만 프롬프트에 미포함. 데이터 길이만 전달. - **CLAUDE.md:** "1차 조립 결과의 전체 균형 확인" - **작업:** _review_balance() 프롬프트에 HTML 구조 요약 또는 전문 포함 - **파일:** pipeline.py `_review_balance()` - **의존성:** 없음 ### A-3: 5단계 shrink action 구현 - **현재:** `_apply_adjustments()`에서 `action in ("expand", "rewrite")` 조건만 처리. shrink 무시. - **작업:** shrink 시 char_guide 값을 0.7배로 축소하는 분기 추가 - **파일:** pipeline.py `_apply_adjustments()` - **의존성:** 없음 ### A-4: 5단계 rewrite action 구현 - **현재:** rewrite가 expand와 같은 조건에 들어가지만 실제 동작 없음 (no-op). - **작업:** rewrite 시 해당 블록의 data를 초기화하고 fill_content()로 재편집 - **파일:** pipeline.py `_apply_adjustments()` - **의존성:** 없음 ### A-5: overflow:hidden vs "텍스트 자르지 않는다" 원칙 해소 - **현재:** base.css에 `.slide { overflow: hidden }` + `.slide > div { overflow: hidden }`. 텍스트 넘치면 잘림. - **CLAUDE.md:** "텍스트를 자르지 않는다 (디자인이 텍스트에 맞춘다)" - **작업:** A-1(Sonnet 디자인 조정)으로 넘침을 사전 방지. `.slide > div`의 overflow를 재검토. 최소한 텍스트 블록은 overflow: visible 또는 auto 허용. - **파일:** static/base.css - **의존성:** A-1 완료 후 정책 결정 ### A-6: object-fit: cover → contain 수정 - **현재:** image-row-2col.html, image-grid-2x2.html에서 `object-fit: cover` 사용 → 이미지 crop 발생 - **CLAUDE.md:** "이미지를 crop하지 않는다", "object-fit: contain" - **작업:** cover → contain으로 변경 - **파일:** templates/blocks/media/image-row-2col.html, templates/blocks/media/image-grid-2x2.html - **의존성:** 없음 ### A-7: table-layout: fixed 적용 - **현재:** compare-3col-badge.html에 table-layout 미지정 - **CLAUDE.md:** "table-layout: fixed" - **작업:** 테이블 CSS에 table-layout: fixed 추가 - **파일:** templates/blocks/tables/compare-3col-badge.html - **의존성:** 없음 ### A-8: container query 폰트 스케일링 - **현재:** 표 셀 폰트 크기 고정 - **CLAUDE.md:** "container query 폰트 스케일링" - **작업:** @container 규칙으로 표 크기에 따른 폰트 자동 축소 - **파일:** templates/blocks/tables/compare-3col-badge.html - **의존성:** A-7 --- ## Phase B: 누락 기능 구현 (8개) > **실행 상세:** [IMPROVEMENT-PHASE-B.md](IMPROVEMENT-PHASE-B.md) ### B-1: details-block 템플릿 제작 - **현재:** BLOCK_SLOTS에 정의만 있고 HTML 템플릿 파일 없음. 렌더링 불가. - **CLAUDE.md:** "HTML 네이티브 `
/` 사용" - **작업:** `
/` 기반 접기/펼치기 블록 템플릿 제작 - **파일:** 신규 templates/blocks/emphasis/details-block.html - **의존성:** 없음 ### B-2: 인쇄 시 details 자동 펼침 JS - **현재:** 미구현 - **CLAUDE.md:** "인쇄 시 JavaScript 6줄로 자동 펼침" - **작업:** slide-base.html에 `window.onbeforeprint` 핸들러 추가 - **파일:** templates/slide-base.html - **의존성:** B-1 ### B-3: catalog에 details-block 등록 - **현재:** catalog.yaml에 미등록 → 팀장이 선택 불가 - **작업:** id, when, not_for, slots, height_cost 정의하여 등록 - **파일:** templates/catalog.yaml - **의존성:** B-1 ### B-4: 1단계 이미지 상세 판단 필드 - **현재:** `content_type: "image"` 한 줄만. 개수/소속/핵심여부/텍스트포함 없음. - **CLAUDE.md:** "몇 개인지, 어떤 꼭지 소속인지, 핵심/보조인지, 텍스트 포함 이미지인지" - **작업:** KEI_PROMPT 출력 형식에 images[] 배열 추가 (count, topic_id, role, has_text) - **파일:** src/kei_client.py KEI_PROMPT - **의존성:** 없음 ### B-5: 1단계 표 상세 판단 필드 - **현재:** `content_type: "table"` 한 줄만. 행/열 규모 없음. - **CLAUDE.md:** "행/열 규모, 전체 표시 가능 여부" - **작업:** KEI_PROMPT 출력 형식에 tables[] 배열 추가 (rows, cols, fits_single_page) - **파일:** src/kei_client.py KEI_PROMPT - **의존성:** 없음 ### B-6: ~~catalog에 quote-left-border 등록 여부~~ → 제외 확정 - **결정 (2026-03-25):** 등록 안 함. 구 블록 제거 방향 유지. 신규 블록(quote-question)만 사용. - **상태:** 해결됨 (작업 불필요) ### B-7: ~~catalog에 comparison-2col 등록 여부~~ → 제외 확정 - **결정 (2026-03-25):** 등록 안 함. 구 블록 제거 방향 유지. 신규 블록(compare-box, comparison-table)만 사용. - **상태:** 해결됨 (작업 불필요) ### B-8: fallback_layout에서 card-grid → 신규 블록 교체 - **현재:** `_fallback_layout()`에서 삭제된 `"card-grid"` 타입 사용 (design_director.py:438) - **작업:** card-image 또는 topic-header 등 신규 블록으로 교체 - **파일:** src/design_director.py `_fallback_layout()` - **의존성:** 없음 --- ## Phase C: 디자인 원칙 위반 수정 (4개) > **실행 상세:** [IMPROVEMENT-PHASE-C.md](IMPROVEMENT-PHASE-C.md) ### C-1: ~~HTML/CSS 블록 배경 그라데이션 제거~~ → CLAUDE.md 원칙 완화 - **결정 (2026-03-25):** banner-gradient의 그라데이션은 디자인의 핵심. 코드 수정 대신 CLAUDE.md 원칙을 완화. - **작업:** CLAUDE.md의 "HTML/CSS 블록의 배경 그라데이션 금지" → "디자인 의도가 명확한 블록(배너, 오버레이 등)은 허용" 으로 업데이트 - **파일:** CLAUDE.md - **상태:** CLAUDE.md 업데이트만 필요 ### C-2: hover 효과 제거 - **현재:** compare-3col-badge.html에 `tr:hover` 배경색 변경 - **CLAUDE.md:** "호버 효과 금지" - **작업:** :hover 규칙 삭제 - **파일:** templates/blocks/tables/compare-3col-badge.html - **의존성:** 없음 ### C-3: border-radius > 8px 수정 - **현재:** quote-question(12px), compare-pill-pair(60px), card-dark-overlay(10px), card-text-grid(12px), compare-3col-badge(25px) - **CLAUDE.md:** "둥근 모서리 과다 사용 금지 (border-radius 최대 8px)" - **작업:** 모두 var(--radius)(6px) 또는 최대 8px로 조정 - **파일:** 5개 html 파일 - **의존성:** 없음. 단, compare-pill-pair(60px)는 "pill" 모양이 디자인 의도 — 이 블록은 SVG 전환(E-2) 시 해결될 수 있음 ### C-4: circle-gradient box-shadow 2레벨 → 1레벨 - **현재:** 2개 box-shadow (0 0 30px + 0 0 60px) - **CLAUDE.md:** "그림자 최소화 (1개 레벨만)" - **작업:** shadow 1개로 축소. 또는 SVG 전환(E-1) 시 filter로 대체 - **파일:** templates/blocks/visuals/circle-gradient.html - **의존성:** 없음 --- ## Phase D: 이미지 처리 — Pillow 도입 (6개) > **실행 상세:** [IMPROVEMENT-PHASE-D.md](IMPROVEMENT-PHASE-D.md) > MDX 콘텐츠에 `![alt](/assets/images/DX1.png)` 같은 이미지 참조가 포함됨. > 이미지 파일은 로컬 디스크에 존재 (MDX 프로젝트 폴더 기준 상대 경로). > 서버가 localhost에서 돌므로 로컬 파일 접근 가능. ### D-0: 이미지 경로 입력 UI + API 파라미터 (선행 작업) - **현재:** 프론트엔드에서 텍스트만 전송. 이미지 기준 경로 전달 방법 없음. - **필요 이유:** 이미지 상대 경로(`/assets/images/DX1.png`)를 절대 경로로 해석하려면 base_path 필요. - **작업:** - 프론트엔드(static/index.html): 텍스트에서 `![...](...)` 패턴 감지 → 발견 시 "이미지 폴더 위치" 입력 팝업 표시 - API(src/main.py): `/api/generate` 엔드포인트에 `base_path` 선택 파라미터 추가 - 파이프라인(src/pipeline.py): `generate_slide()`에 `base_path` 전달 - **파일:** static/index.html, src/main.py, src/pipeline.py - **의존성:** 없음 ### D-1: Pillow 이미지 크기 읽기 유틸리티 - **현재:** Pillow import/사용 전무. pyproject.toml에도 없음. src/utils/ 디렉토리 없음. - **CLAUDE.md:** "Pillow Image.open().size (헤더만 읽음)" - **작업:** - pyproject.toml에 `Pillow>=10.0` 추가 - 유틸리티 함수: base_path + 상대 경로 → Pillow로 (width, height) 반환 - 콘텐츠 텍스트에서 `![alt](path)` 패턴 추출 → 각 이미지 크기 측정 - **파일:** pyproject.toml, 신규 src/image_utils.py - **의존성:** D-0 (base_path 전달 체계) ### D-2: 가로형 이미지(ratio > 1.2) → 전체 너비 배치 - **현재:** 비율 기반 배치 판단 없음 - **작업:** 파이프라인에서 이미지 크기/비율 정보를 2단계 Step B와 4단계 Sonnet에 전달. 팀장/실무자가 배치 판단. - **파일:** src/pipeline.py 또는 src/design_director.py - **의존성:** D-1 ### D-3: 세로형 이미지(ratio < 0.8) → 텍스트 옆 배치 - **현재:** 미구현 - **작업:** D-2와 함께 구현. 비율 정보를 프롬프트에 포함하면 AI가 배치 판단. - **파일:** src/design_director.py - **의존성:** D-1 ### D-4: 텍스트 포함 도표 → 과도한 축소 방지 - **현재:** 미구현 - **작업:** B-4에서 추가한 images[].has_text 정보와 D-1의 크기 정보를 결합. has_text=true이면 "이 이미지는 축소하지 마라" 프롬프트 가이드. - **파일:** src/design_director.py - **의존성:** D-1, B-4 (이미지 상세 판단) ### D-5: 슬라이드 HTML에 이미지 경로 삽입 - **현재:** 이미지 블록(image-row, image-side-text 등)은 src 슬롯에 URL/경로를 넣지만, 실제 이미지 경로가 연결 안 됨. - **작업:** 렌더링된 HTML에서 이미지 상대 경로를 절대 경로 또는 data URI(base64)로 변환하여 다운로드 HTML에서도 이미지 표시. - **파일:** src/renderer.py 또는 src/pipeline.py - **의존성:** D-0, D-1 --- ## Phase E: visuals 블록 SVG 전환 (3개) — Phase 2 이후 진행 > **Phase 2 이후로 연기.** > 다른 Claude가 Phase 2에서 `svg_calculator.py`(좌표 계산 모듈) + `renderer.py`에 `_preprocess_svg_data()` + `venn-diagram.html` 동적 템플릿 작업 중. > Phase E는 이 인프라 위에서 나머지 3개 블록을 SVG로 전환하는 작업이므로, Phase 2 완료 후 진행해야 함. > > **활용 방식:** `svg_calculator.py`에 각 블록용 좌표 함수 추가 + `_preprocess_svg_data()`에 블록 등록. > > **P2-D(shrink/rewrite)는 Phase A(A-3/A-4)에서 이미 구현 완료.** 다른 Claude에게 중복 방지 알림 필요. ### E-1: circle-gradient → SVG - **현재:** CSS border-radius + linear-gradient - **작업:** SVG `` + `` + ``로 재제작. `svg_calculator.py`에 함수 추가. - **파일:** templates/blocks/visuals/circle-gradient.html, src/svg_calculator.py - **의존성:** Phase 2 P2-B 완료 ### E-2: compare-pill-pair → SVG - **현재:** HTML div + CSS border-radius: 60px - **작업:** SVG `` + ``로 재제작. C-3 border-radius 위반도 해소. - **파일:** templates/blocks/visuals/compare-pill-pair.html - **의존성:** Phase 2 P2-B 완료 ### E-3: process-horizontal → SVG - **현재:** HTML/CSS flexbox + 가상 화살표 - **작업:** SVG `` + `` + `` + ``로 재제작. `svg_calculator.py`에 함수 추가. - **파일:** templates/blocks/visuals/process-horizontal.html, src/svg_calculator.py - **의존성:** Phase 2 P2-B 완료 --- ## Phase F: 향후 — Phase 2 이후 (6개) ### F-1: Step A를 AI 선택으로 전환 - **현재:** 규칙 기반 4줄 코드 (CLAUDE.md에는 "규칙 기반"으로 명시) - **대화에서 요청됨:** AI가 프리셋을 선택하도록 변경 - **작업:** select_preset()을 Sonnet 호출로 전환. CLAUDE.md 업데이트. - **의존성:** CLAUDE.md 원칙 변경 합의 ### F-2: Gemini API 배경 생성 - **현재:** 미구현 - **CLAUDE.md:** "실사 배경: Gemini API (배경 텍스처 전용)" - **작업:** section-title-with-bg 등의 배경 이미지를 Gemini로 생성 - **의존성:** Gemini API 키 ### F-3: FAISS 블록 검색 - **현재:** 미구현 (PLAN.md DA-20) - **CLAUDE.md:** "변형 40개 이상부터 FAISS 도입 검토" - **작업:** 블록 HTML 구조/용도 임베딩 → FAISS 인덱스 → 검색 - **의존성:** DA-19 (변형 40개+) ### F-4: venn-diagram N개 자동 배치 (cos/sin) - **현재:** Phase 1 — 3개 고정 SVG - **CLAUDE.md:** "Phase 2: N개 자동 배치 (360/N 간격, cos/sin)" - **작업:** renderer에서 items 개수에 따라 좌표 계산 후 템플릿에 전달 - **의존성:** 없음 ### F-5: Figma REST API 연동 - **현재:** 수동 에셋만 (docs/figma-assets/) - **작업:** Figma API로 에셋 자동 추출 - **의존성:** Figma API 키 ### F-6: .astro (Starlight) 출력 - **현재:** HTML 다운로드만 - **작업:** HTML → .astro 변환 출력 옵션 - **의존성:** Starlight 연동 설계 --- ## Phase G: Kei API 통신 정상화 (4개) > **실행 상세:** [IMPROVEMENT-PHASE-G.md](IMPROVEMENT-PHASE-G.md) > design_agent만 수정. persona_agent 코드 수정 0건. ### G-1: httpx non-streaming → streaming 전환 (핵심) - **문제:** httpx `client.post()`가 SSE 전체 응답 완료까지 대기 (30분+) - **해결:** `client.stream("POST", ...)`로 전환. SSE 토큰 실시간 수신. - **파일:** kei_client.py, content_editor.py, design_director.py ### G-2: Sonnet fallback 완전 제거 - **문제:** 사용자 요청 "Kei API만 사용"인데 Sonnet fallback이 남아있음 - **해결:** fallback 분기 제거. Kei API 실패 시 에러 반환. - **파일:** kei_client.py, content_editor.py ### G-3: `_parse_json()` 마크다운 제거 3파일 동기화 - **문제:** kei_client.py에만 `- ` 제거 있고, content_editor/design_director에 없음 - **해결:** 3개 파일의 `_parse_json()` 동기화 - **파일:** content_editor.py, design_director.py ### G-4: FAISS를 CPU로 전환 (GPU 메모리 경쟁 해소) - **문제:** persona_agent + design_agent가 같은 GPU 경쟁 → OOM - **해결:** design_agent의 FAISS를 CPU로 전환 (46개 블록이므로 충분히 빠름) - **파일:** block_search.py, build_block_index.py --- ## Phase H: 스토리라인 설계 기반 파이프라인 전환 (4개) > **실행 상세:** [IMPROVEMENT-PHASE-H.md](IMPROVEMENT-PHASE-H.md) > 코드 구조 변경 없음. 프롬프트 3개만 수정. 원본 텍스트 최대 보존. ### H-1: KEI_PROMPT 재설계 — "꼭지 추출" → "스토리라인 설계" - **문제:** 꼭지만 추출하고 전체 스토리 흐름 없음 - **해결:** "이 슬라이드의 스토리를 설계해줘" + core_message + purpose + source_hint - **파일:** kei_client.py ### H-2: EDITOR_PROMPT 수정 — 원본 텍스트 최대 보존 - **문제:** "세련된 편집"으로 과도한 재작성 - **해결:** "원본 보존, 약간만 축약, 빈 슬롯 금지" - **파일:** content_editor.py ### H-3: STEP_B_PROMPT 보강 — purpose 기반 블록 선택 - **문제:** 형태만 보고 블록 매칭. 목적 모름. - **해결:** purpose별 블록 선택 가이드 (문제제기→경고, 정의→카드 등) - **파일:** design_director.py ### H-4: 3단계 편집자에게 purpose 전달 - **문제:** 편집자가 "이 블록이 왜 여기 있는지" 모름 - **해결:** slot_requirements에 purpose 포함 - **파일:** content_editor.py --- ## Phase I: 전수 정합성 복구 + 넘침 처리 패러다임 전환 (14개) ✅ 완료 > **실행 상세:** [IMPROVEMENT-PHASE-I.md](IMPROVEMENT-PHASE-I.md) > 전수 검토에서 발견된 프롬프트 자기모순 + 슬롯 의미 미전달 + 코드 안전망 부족 해결. > **핵심 변경: 넘침 시 DOWNGRADE_MAP 자동 교체 → Kei 판단 호출로 전환.** ### Phase I-A: 정합성 복구 (7개) ✅ - I-14: `_stream_sse_tokens()` 3개 파일 중복 → `src/sse_utils.py` 공통 유틸 추출 - I-13: dead code 3건 삭제 (`_call_anthropic_direct`, `_extract_sse_text` x2) + `import anthropic` 제거 - I-1: STEP_B_PROMPT purpose 가이드 미존재 블록 3개 → 실존 블록으로 교체 - I-2: catalog.yaml not_for 13건 미존재 블록 참조 교체/제거 - I-12: BLOCK_SLOTS 주석 개수 수정 (cards 9, visuals 6, emphasis 10) - I-10: INDEX.md 38개로 동기화 (삭제된 8개 블록 행 제거) - I-11: README.md 38개로 동기화 (_legacy 제거, 트리/개수 정리) ### Phase I-B: 블록 선택 + 슬롯 의미 (5개) ✅ - I-3: `PURPOSE_FALLBACK` 상수 + purpose 기반 미등록 블록 교체 - I-7: compare-pill-pair 단독 사용 금지 검증 (`COMPARISON_BLOCKS`) - I-4: 38개 블록 전체에 `slot_desc` 추가 (각 슬롯 의미/형식/예시) - I-5: 편집자 프롬프트에 slot_desc 전달 로직 (Kei API 경유) - I-6: 제목 유사도 70% 초과 시 자동 교정 (`SequenceMatcher`) ### Phase I-C: 넘침 처리 패러다임 전환 (2개) ✅ - I-9: `_validate_height_budget()` → overflow 반환 (블록 교체 안 함) + `_downgrade_fallback()` 비상 분리 + `KEI_OVERFLOW_PROMPT` + `call_kei_overflow_judgment()` Kei API 호출 + pipeline Stage 2.5 추가 (trim/restructure 분기) - I-8: 대형 콘텐츠(테이블/이미지) 정보를 Kei overflow 프롬프트에 포함 --- ## 프로세스 재검토: 검증 시점 문제 (Phase I 후속) > **상세:** [IMPROVEMENT-PROCESS-REVIEW.md](IMPROVEMENT-PROCESS-REVIEW.md) > Phase I 실행 후 발견. Stage 2.5의 넘침 판단이 텍스트 없는 시점에서 실행되는 구조적 문제. **문제:** 6건 (내용 없이 판단, 판단 주체 잘못됨, HTML 있는데 넘침 안 봄, Kei 없음, 높이 측정 없음, 루프에 누락) **원인:** Phase I에서 DOWNGRADE_MAP → Kei 판단으로 메커니즘만 변경, 위치(Stage 2.5)는 기존 코드 관성으로 유지 **해결:** Stage 2.5 제거 → Stage 5에서 Sonnet 감지 + Kei 판단 통합 - P-1: Stage 2.5 제거 (pipeline.py) - P-2: `_review_balance()` 프롬프트에 zone 예산 + overflow_detected 추가 - P-3: Stage 5 루프에 Kei 넘침 판단 통합 - P-4: `_apply_adjustments()` kei_trim/kei_restructure action 추가 - P-5: 호출부 analysis 파라미터 추가 **Phase I 영향:** 회귀 없음. `call_kei_overflow_judgment()`, `_downgrade_fallback()`, `KEI_OVERFLOW_PROMPT` 전부 재사용. 호출 위치만 이동. --- ## Phase J: 블록 선택 권한 구조 재정의 + 최종 검토 Kei 전환 (7개) ✅ 완료 > **실행 상세:** [IMPROVEMENT-PHASE-J.md](IMPROVEMENT-PHASE-J.md) > Phase I 완료 후 결과물 3회 비교에서 확인. Sonnet(팀장)이 Opus(실장) 추천을 엎고, 자기가 만든 문제를 자기가 검토하는 구조적 문제. ### Phase J-A: 팀장 권한 제한 + 가이드 수정 (5개) - J-1: STEP_B_PROMPT "Opus 추천 존중" 규칙 강화 — "참고" → "기본 사용, 변경 금지" - J-2: section-header-bar body 사용 금지 — BODY_FORBIDDEN_MAP에 추가 (삭제 처리) - J-3a: purpose 가이드 수정 — 용어정의/근거사례에서 card-icon-desc 제거 → card-numbered - J-3b: catalog.yaml 수정 — "용어 정의 → card-icon-desc" → "card-numbered" - J-6: sidebar 카드 1열 강제 — 템플릿 column_override + design_director 주입 ### Phase J-B: 편집자 강화 (1개) - J-4: source 슬롯 금지 규칙 — EDITOR_PROMPT에 출처 규칙 추가 (Kei 편집자 경유) ### Phase J-C: 최종 검토 Kei 전환 (1개) - J-7: Stage 5 _review_balance() → Kei API 호출로 전환 — KEI_REVIEW_PROMPT + call_kei_final_review() 신규 --- ## Phase K: communicative role 기반 시각적 위계 + 콘텐츠 시퀀싱 (8개) > **실행 상세:** [IMPROVEMENT-PHASE-K.md](IMPROVEMENT-PHASE-K.md) > Phase J 이후에도 결과물 품질 미개선. purpose를 분류하고도 시각적 결과에 반영하지 않은 것이 근본 원인. > 사용자 반복 요청(콘텐츠 구조 흐름)을 이번에 전부 반영. ### K-Step 1: 콘텐츠 설계 (가장 중요) - K-1: purpose → 시각적 위계 매핑 (핵심전달=주인공, 문제제기=compact) - K-2: purpose 기반 인지 흐름 순서 원칙 (하드코딩 아닌 원칙) - K-4: purpose별 분량 제약 (문제제기 max 100자, 핵심전달 200-400자 등) ### K-Step 2: 블록 선택 정확성 - K-3: purpose별 허용/금지 블록 매핑 - K-6: sidebar 시각적 무게 조절 - K-8: 비교 블록 맥락 안내 ### K-Step 3: 코드 + 검수 - K-5: column_override 보존 (content_editor.py) - K-7: Kei 검수에 구조 흐름 검증 추가 --- ## Phase K-1: 파이프라인 스텝별 중간 산출물 로컬 저장 > **실행 상세:** [IMPROVEMENT-PHASE-K1.md](IMPROVEMENT-PHASE-K1.md) > 각 스텝에서 뭘 결정했고 왜 그렇게 했는지를 파일로 저장. 사용자가 확인하고 피드백 가능. - `data/runs/{timestamp}/` 폴더에 step별 JSON + HTML 저장 - step1 (Kei 분석) → step2 (블록 매핑) → step3 (텍스트) → step4 (렌더링) → step5 (검수) → final --- ## Phase L: 렌더링 측정 에이전트 + Purpose 기반 공간 할당 + 수학적 조정 (11건) > **실행 상세:** [IMPROVEMENT-PHASE-L.md](IMPROVEMENT-PHASE-L.md) > Phase I~K에서 미충족 7건 + 부분충족 4건의 근본 원인: 실제 렌더링 px 측정 없음. > LLM 추정이 아닌 코드 계산 + 브라우저 측정으로 전환. ### L-Step 1: 공간 할당 엔진 - PURPOSE_WEIGHT 비율 할당 + allocate_height_budget() 함수 - calculate_trim_chars() 수학적 글자 수 계산 ### L-Step 2: 렌더링 측정 에이전트 - measure_rendered_heights() — Selenium headless - 각 zone/block의 scrollHeight, clientHeight, overflow 정확 측정 ### L-Step 3: CSS max-height 제약 - purpose별 할당 높이를 CSS max-height로 적용 - 물리적으로 넘치지 않게 구조적 보장 ### L-Step 4: 피드백 루프 - 측정 → 초과 시 수학적 축약량 계산 → 편집자 재호출 → 재측정 - Kei 검수에 실제 px 수치 전달 → 근거 있는 검수 --- ## Phase M: 비중 시스템 + 역할-블록 매핑 + 블록 안전성 + 원본 보존 (9건) > **실행 상세:** [IMPROVEMENT-PHASE-M.md](IMPROVEMENT-PHASE-M.md) > P-1~P-9 문제점 전수 진단. 비중 시스템(Kei 판단, 하드코딩 아님) 기반 전면 재설계. ### M-Step 1: [긴급] Kei 비중 시스템 (P-1 + P-2 + P-4) - Kei가 콘텐츠마다 본심/배경/첨부/결론 + weight 판단 - PURPOSE_WEIGHT 하드코딩 제거 → Kei 출력 weight 사용 - weight → px 변환 → 블록 크기/배치 자동 결정 ### M-Step 2: [중요] 역할-블록 매핑 (P-3) - 역할 × 콘텐츠 성격 → 블록 결정 매트릭스 --- ## Phase N: 4대 핵심 문제 해결 ✅ 완료 > **실행 상세:** [IMPROVEMENT-PHASE-N.md](IMPROVEMENT-PHASE-N.md) > catalog 개선, fallback 전면 제거, topic_id 버그 수정, 무한 재시도 체계. - N-1: 블록 선택 코드 레벨 강제 — Kei 확정 블록을 Sonnet이 변경 불가 + topic_id/id 양쪽 체크 - N-2: 사이드바 섹션 제목 — Kei가 section_title 출력 + divider-text 자동 삽입 - N-3: max-height CSS 래퍼 제거 — 콘텐츠는 _max_chars로 사전 조절, CSS로 사후 자르기 금지 - N-4: Stage 5 스크린샷 검수 — Selenium 스크린샷 → Opus 멀티모달로 실제 렌더링 보고 검수 - **Kei API 무한 재시도** — 모든 Kei API 호출을 성공할 때까지 무한 재시도. fallback/기본값/rule-based 대체 전면 제거 - **catalog.yaml 전면 개선** — 38개 블록의 when/not_for/purpose_fit 재작성 + FAISS 인덱스 재빌드 - **삭제:** manual_classify(), _apply_defaults(), _downgrade_fallback(), PURPOSE_FALLBACK 대체용 코드 --- ## Phase O: 컨테이너 기반 레이아웃 시스템 🟡 진행 중 > **실행 상세:** [IMPROVEMENT-PHASE-O.md](IMPROVEMENT-PHASE-O.md) > Phase N 완료 후 여전히 비중이 시각에 반영 안 되는 근본 문제 해결. **핵심 원칙:** "비중이 컨테이너를 확정 → 컨테이너가 블록을 제약 → 블록이 콘텐츠를 제약" - O-1: 컨테이너 스펙 계산 — ✅ 완료 (calculate_container_specs) - O-2: 블록 선택에 컨테이너 제약 전달 — ✅ 완료 (Kei 프롬프트 + height_cost 검증) - O-3: 블록 스펙 확정 — ✅ 완료 (finalize_block_specs) - O-4: 편집자에 블록 스펙 전달 — ✅ 완료 (_container_height_px, _max_items 등) - O-5: 렌더러 비중 기반 grid row — ✅ 완료 (container div 생성) - O-6: 파이프라인 흐름 변경 — ✅ 완료 (Phase M 코드 교체) - O-7: 리포트 확장 — 🟡 미완 (새 중간 산출물 표시 추가 필요) - **미세 조정 필요:** 배경 117px / topic 2개 = 58px에 medium 블록 안 맞는 문제 - **Selenium 측정:** container div 셀렉터 추가 필요 ### Step B 제거 + 죽은 코드 정리 ✅ 완료 Phase O에서 Kei(A-2) + 코드가 모든 것을 결정하면서 Step B(Sonnet)가 완전히 무력화됨 → 제거. **삭제된 코드:** - `STEP_B_PROMPT` (~100줄 프롬프트) - Step B Sonnet API 호출 코드 (~250줄) - `_fallback_layout()` (Step B 실패 시 rule-based) - `PURPOSE_FALLBACK` (미등록 블록 대체) - `DOWNGRADE_MAP` (블록 다운그레이드) - `_downgrade_fallback()` (비상 교체) - `_apply_defaults()` (편집 실패 시 기본값) - `import anthropic` (design_director.py에서) - O-6: 파이프라인 흐름 변경 — 1B 후 컨테이너 계산, Step B 후 블록 스펙 확정 - O-7: 리포트에 컨테이너/블록 스펙 표시 **기존 코드 교체 (충돌 해결):** - `_max_height_px` → `_container_height_px` (pipeline.py 155~198행 교체) - `allocate_height_budget()` → `calculate_container_specs()` (호출부 교체) - `_max_chars` 단일값 → `_max_items` + `_max_chars_per_item` (content_editor.py 교체) - Selenium `_MEASURE_SCRIPT` — container div 셀렉터 추가 - Phase L 축소 로직 — `_max_chars_total` 축소로 변경 - fonttools 의존성 + Pretendard .ttf 파일 추가 ### M-Step 3: [중요] 블록 안전성 (P-5 + P-6 + P-7 + P-8) - Figma 블록 식별, zone 적합성 맵, 글자 수용량, 내부 overflow 감지 ### M-Step 4: [보통] 원본 보존 (P-9) - source_text 직접 전달, 재작성 금지 강화 --- ## Phase별 의존 관계 ``` Phase A (슬라이드 품질) ├── A-1~A-4: 독립 작업 가능 ├── A-5: A-1 완료 후 ├── A-6, A-7: 독립 └── A-8: A-7 완료 후 Phase B (누락 기능) ├── B-1~B-5, B-8: 독립 ├── B-2, B-3: B-1 완료 후 └── B-6, B-7: 사용자 결정 대기 Phase C (디자인 원칙) → 독립. A/B와 병렬 가능. └── C-1: 사용자 결정 대기 (원칙 변경 vs 코드 수정) Phase D (Pillow) → D-1 선행, 나머지 순차 └── D-4: B-4 완료 후 Phase E (SVG 전환) → 독립. A/B/C와 병렬 가능. Phase F (향후) → Phase A~E 완료 후. └── F-1: CLAUDE.md 합의 후 ``` --- ## 수정 이력 | 날짜 | 내용 | |------|------| | 2026-03-25 | 초안 작성. CLAUDE.md 전수검토 기반 33개 항목 도출. |