전체 26 files (20 추가 + 6 수정), 10507 insertions. Phase Z 문서 : - docs/architecture/PHASE-Z-CHANGE-LOG.md (신설) — axis-by-axis 의사결정 history (newest-on-top). Step 7-A 부터 6 entry 박힘 + 2026-05-08 / 2026-05-08 #2 (compat 매트릭스 폐기 / 6-B 폐기 / F14 표현 정정 / label gate policy 분리). - docs/architecture/PHASE-Z-PIPELINE-OVERVIEW.md (수정) — Step 5/6/9 Gap note append (구조 무변, append-only). 6-B 폐기 사실 + Refinement F. - docs/architecture/PHASE-Z-PIPELINE-STATUS-BOARD.md (수정) — snapshot date 2026-05-08 갱신. §3 핵심 missing item 5 (Step 5/6/9 boundary axis breakdown + 폐기 기록). §6 한 줄 갱신 — 다음 axis 후보 A~F. Project root docs : - PLAN.md / PROGRESS.md / README.md (수정) — 토큰 체계 / 폴더 구조 / 설계 문서 / 역할 분리 반영. - IMPROVEMENT-REDESIGN.md (신설) — Phase Z 설계 핵심 문서. - PROCESS_OVERVIEW.html (신설) — 파이프라인 개요 시각. - docs/tasks/* (신설) — Phase Z task 문서. V4 catalog (Phase Z runtime 필수 의존성) : - tests/matching/v4_full32_result.yaml (신설, 4888 줄) — V4 매칭 결과 32 frame × 10 MDX section. lookup_v4_match() / lookup_v4_candidates() 가 본 파일 read. Phase Z runtime 이 *없으면 즉시 abort* — clone 후 즉시 동작 가능 보장. Samples : - samples/mdx_batch/04.mdx (신설) — MDX04 기본 sample. - samples/mdx/04. DX 지연 요인.mdx (신설) — MDX04 원본. Phase Q legacy 보존 (별 axis "Phase Q audit & salvage" 영역) : - src/block_matcher_tfidf.py / catalog_blocks.py / frame_extractor.py / pipeline_v2.py — Phase Q (옛 파이프라인) src 신규 untracked 파일들. Phase Z runtime 와 의존성 0. Phase Q audit axis 에서 검토 예정. - scripts/eval_block_matcher.py / fetch_all_frame_screenshots.py / match_17_units_my_matcher.py / match_mdx_strict.py / match_mdx_to_frames_tfidf.py / ocr_augment_texts.py / run_pipeline_v2.py / previews/ — Phase Q 작업 시 사용한 옛 script. 같이 보존. - run_mdx03_pipeline.py (수정) — Phase Q 진입점 (no flag) + Phase Z 진입점 (--phase-z2 flag) 동시 wrapper. Phase Z 만 사용 시 `python -m src.phase_z2_pipeline samples/mdx_batch/03.mdx <run_id>` 직접 호출. 비-scope : - tests/matching/ (v4_full32_result.yaml 외 ~63MB) — V4 진화 history / reports / DECK / ATTACH. Phase Q audit axis 에서 검토. - tests/pipeline/ (~15MB) — pipeline data. Phase Q audit 영역. - templates/catalog/blocks.yaml — 옛 block catalog. Phase Q audit. - templates/phase_z2/frames/ — 옛 frame partial 위치. Phase Q audit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
511 lines
24 KiB
Markdown
511 lines
24 KiB
Markdown
# Design Agent — 실행 계획
|
|
|
|
## Phase 1: 기반 구축
|
|
|
|
### DA-1: 프로젝트 셋업
|
|
- **파일:** pyproject.toml, .env, .gitignore
|
|
- **내용:** Python 환경, 의존성 정의, 환경 변수
|
|
- **의존성:** 없음
|
|
- **완료 기준:** `pip install -e .` 성공
|
|
|
|
### DA-2: FastAPI 서버 기본 구조
|
|
- **파일:** src/main.py, src/config.py
|
|
- **내용:** FastAPI 앱, CORS, health endpoint, 설정 관리
|
|
- **의존성:** DA-1
|
|
- **완료 기준:** `uvicorn src.main:app --reload` 정상 시작, `/api/health` 200 반환
|
|
|
|
### DA-3: 디자인 토큰 + 기본 CSS
|
|
- **파일:** static/tokens.css, static/base.css
|
|
- **내용:** CLAUDE.md에 정의된 디자인 토큰을 CSS 변수로 구현, Pretendard 폰트 설정, 16:9 슬라이드 컨테이너
|
|
- **의존성:** 없음
|
|
- **완료 기준:** 빈 슬라이드가 16:9 비율로 렌더링, Pretendard 폰트 적용 확인
|
|
|
|
---
|
|
|
|
## Phase 2: 블록 템플릿 제작
|
|
|
|
### DA-4: 블록 템플릿 — 비교 (comparison)
|
|
- **파일:** templates/blocks/comparison.html
|
|
- **내용:** 2단 병렬 레이아웃, Jinja2 슬롯 ({{left_title}}, {{left_content}}, {{right_title}}, {{right_content}})
|
|
- **의존성:** DA-3
|
|
- **완료 기준:** 더미 데이터로 렌더링 시 2단 비교 표시, 디자인 토큰 적용
|
|
|
|
### DA-5: 블록 템플릿 — 카드 그리드 (card-grid)
|
|
- **파일:** templates/blocks/card-grid.html
|
|
- **내용:** 2~4열 카드 배열, Jinja2 슬롯 ({{cards[n].icon}}, {{cards[n].title}}, {{cards[n].description}})
|
|
- **의존성:** DA-3
|
|
- **완료 기준:** 3개 카드 렌더링, 카드 수에 따라 자동 배열
|
|
|
|
### DA-6: 블록 템플릿 — 관계도 (relationship)
|
|
- **파일:** templates/blocks/relationship.html
|
|
- **내용:** 벤 다이어그램 (CSS 원형), Jinja2 슬롯 ({{center}}, {{items[n]}})
|
|
- **의존성:** DA-3
|
|
- **완료 기준:** 3원 벤 다이어그램 렌더링, 라벨 표시
|
|
|
|
### DA-7: 블록 템플릿 — 프로세스 (process)
|
|
- **파일:** templates/blocks/process.html
|
|
- **내용:** 가로 단계 흐름, Jinja2 슬롯 ({{steps[n].number}}, {{steps[n].title}}, {{steps[n].description}})
|
|
- **의존성:** DA-3
|
|
- **완료 기준:** 4단계 프로세스 렌더링, 연결선 표시
|
|
|
|
### DA-8: 블록 템플릿 — 강조 인용 (quote-block)
|
|
- **파일:** templates/blocks/quote-block.html
|
|
- **내용:** 배경색 + 좌측 라인 + 인용 텍스트, Jinja2 슬롯 ({{quote_text}}, {{source}})
|
|
- **의존성:** DA-3
|
|
- **완료 기준:** 인용 블록 렌더링, 강조 스타일 적용
|
|
|
|
### DA-9: 블록 템플릿 — 결론 바 (conclusion-bar)
|
|
- **파일:** templates/blocks/conclusion-bar.html
|
|
- **내용:** 하단 전체 폭 강조 영역, Jinja2 슬롯 ({{conclusion_text}})
|
|
- **의존성:** DA-3
|
|
- **완료 기준:** 결론 바 렌더링, 강조 색상 적용
|
|
|
|
### DA-10: 블록 템플릿 — 비교 테이블 (comparison-table)
|
|
- **파일:** templates/blocks/comparison-table.html
|
|
- **내용:** 다항목 비교 테이블, Jinja2 슬롯 ({{headers}}, {{rows}})
|
|
- **의존성:** DA-3
|
|
- **완료 기준:** 5행 3열 테이블 렌더링
|
|
|
|
### DA-11: 슬라이드 조합 렌더러
|
|
- **파일:** src/renderer.py, templates/slide-base.html
|
|
- **내용:** Jinja2로 블록 조합 → HTML 생성. grid-template-areas로 블록 배치. 다중 페이지 지원.
|
|
- **다중 페이지:** `.slide` div 여러 개 + `page-break-after: always` (인쇄 시 페이지 분리)
|
|
- **의존성:** DA-4 ~ DA-10
|
|
- **완료 기준:** JSON 블록 배치 명세 → 완성 HTML 출력 (1페이지 또는 다중 페이지)
|
|
|
|
---
|
|
|
|
## Phase 3: AI 파이프라인 연결
|
|
|
|
### DA-12: 1단계 — Kei 실장 (꼭지 추출 + 분석)
|
|
- **파일:** src/kei_client.py
|
|
- **내용:** 본문에서 핵심 꼭지 추출 + 다단계 분석
|
|
- 꼭지 추출: 본문에서 2~5개 핵심 파트 식별 (1페이지 적정: 5개)
|
|
- 페이지 분리: 5개 초과 + 레이어 동등 → 2페이지 (의미 기반 분할 2/3, 3/4 등)
|
|
- 5개 + 내용 많음 → 세부 내용은 자세히보기 대상
|
|
- 레이어 수준: 각 꼭지가 도입/핵심/보조/결론 중 어디인지
|
|
- 강조 판단: 어떤 꼭지를 시각적으로 눈에 띄게 할 것인가
|
|
- 배치 방향: 세로로 긴 꼭지, 가로로 나열할 꼭지 판단
|
|
- 이미지 판단: 몇 개, 어떤 꼭지 소속, 핵심/보조, 텍스트 포함 여부
|
|
- 표 판단: 행/열 규모, 전체 표시 가능 여부
|
|
- 상세 콘텐츠 판단: 자세히보기 대상 식별
|
|
- **기술:** Anthropic API (Sonnet)
|
|
- **의존성:** DA-2
|
|
- **완료 기준:** 꼭지 목록 + 레이어 + 강조 + 배치 + 이미지/표/상세 판단 JSON
|
|
|
|
### DA-13a: 2단계 Step A — 레이아웃 프리셋 선택 (규칙 기반)
|
|
- **파일:** src/design_director.py (`select_preset()` 함수)
|
|
- **내용:** 실장의 role 분석을 보고 레이아웃 프리셋을 자동 선택
|
|
- reference 꼭지 있음 → `sidebar-right` (65:35)
|
|
- 모든 flow가 대등 비교 → `two-column` (50:50)
|
|
- 고강조 1개 + 나머지 보조 → `hero-detail`
|
|
- 나머지 → `single-column`
|
|
- **기술:** Python 규칙 코드 (LLM 불필요)
|
|
- **의존성:** DA-12
|
|
- **완료 기준:** 프리셋 이름 + CSS grid 반환
|
|
|
|
### DA-13b: 2단계 Step B — 프리셋 내 블록 매핑 (Sonnet)
|
|
- **파일:** src/design_director.py
|
|
- **내용:** 선택된 프리셋의 zone에 꼭지를 배정 + 블록 타입 선택 + 글자 수 가이드
|
|
- 프롬프트에 선택된 프리셋의 CSS grid가 포함됨
|
|
- flow 꼭지 → body/main zone
|
|
- reference 꼭지 → sidebar zone
|
|
- detail_target → popup 연결
|
|
- catalog에서 블록 타입 선택
|
|
- 이미지/표 배치 판단
|
|
- **기술:** Anthropic API (Sonnet) + Pillow
|
|
- **의존성:** DA-13a
|
|
- **완료 기준:** zone별 블록 배정 + 글자 수 가이드 JSON
|
|
|
|
### DA-13c: 3단계 — Kei 텍스트 편집자 (텍스트 정리)
|
|
|
|
- **파일:** src/content_editor.py
|
|
- **내용:** 팀장의 글자 수 가이드 참고하되 내용 의미 우선
|
|
- 전체 컨텍스트와 핵심 용어 유지
|
|
- 세련된 표현으로 편집 (의미 > 글자 수)
|
|
- 출처 보존, 개조식, 날조 금지
|
|
- 표 내용 편집 (핵심 행/열 선택, 요약)
|
|
- 자세히보기 대상: 요약 버전 + 상세 버전 둘 다 작성
|
|
- **기술:** Anthropic API (Sonnet)
|
|
- **의존성:** DA-13b
|
|
- **완료 기준:** 슬롯별 텍스트 JSON. 핵심 용어 보존. 자세히보기 포함.
|
|
|
|
### DA-14: 4단계 — 디자인 실무자 (디자인 조정 + HTML 조립) + 5단계 재검토
|
|
- **파일:** src/pipeline.py, src/renderer.py
|
|
- **내용:**
|
|
- 4단계 (AI + 코드): 편집자 텍스트에 맞게 디자인 조정 (폰트/여백/박스 — 텍스트 자르지 않음)
|
|
+ Jinja2 HTML 조립, 이미지 object-fit:contain, 표 container query, `<details>` 접기, 인쇄 펼침 JS
|
|
- 5단계 (AI): 팀장이 전체 균형 재검토 → 채움 비율, 블록 균형, 이미지/표 크기 점검 → 2차 조정
|
|
- **기술:** Anthropic API Sonnet (디자인 조정 + 재검토) + Jinja2/CSS (조립)
|
|
- **의존성:** DA-11, DA-12, DA-13a, DA-13b, DA-13c
|
|
- **완료 기준:** 텍스트 입력 → 균형 잡힌 슬라이드 HTML (이미지/표/자세히보기 포함, 재검토 완료)
|
|
|
|
---
|
|
|
|
## Phase 4: UI + 출력
|
|
|
|
### DA-15: 프론트엔드 — 콘텐츠 입력 + 미리보기
|
|
- **파일:** static/index.html (별도 HTML 파일), main.py (FileResponse로 서빙)
|
|
- **내용:** 텍스트 입력 영역 + iframe 미리보기 + HTML 다운로드 버튼
|
|
- **기술:** FileResponse (FastAPI 내장), fetch API + 수동 SSE 파싱
|
|
- **의존성:** DA-14
|
|
- **완료 기준:** 텍스트 붙여넣기 → 슬라이드 미리보기 표시 + HTML 다운로드
|
|
- **주의:** HTML/JS를 Python 문자열에 넣지 않는다 (이스케이프 충돌 방지)
|
|
|
|
---
|
|
|
|
## 버그 수정
|
|
|
|
### BF-2: 블록 내용 비어있음 (렌더러 Jinja2 include 문제)
|
|
- **파일:** src/renderer.py, templates/slide-base.html
|
|
- **내용:** `include` → 블록별 개별 `render()` 후 HTML 삽입
|
|
- **기술:** Jinja2 `get_template().render()` (내장)
|
|
- **의존성:** 없음 (기존 코드 수정만)
|
|
- **완료 기준:** 콘텐츠 입력 → 슬라이드에 텍스트가 표시됨
|
|
|
|
### BF-3: 한글 깨짐 (다운로드 파일)
|
|
- **파일:** static/index.html
|
|
- **내용:** download() Blob에 UTF-8 BOM 추가
|
|
- **기술:** JavaScript `'\uFEFF'` 1줄
|
|
- **의존성:** 없음
|
|
- **완료 기준:** 다운로드한 HTML 파일에서 한글 정상 표시
|
|
|
|
### BF-4: body 블록 겹침 (같은 area에 여러 div)
|
|
- **파일:** src/renderer.py
|
|
- **내용:** 같은 area의 블록을 하나의 div로 그룹핑 (OrderedDict + flex-column)
|
|
- **기술:** Python OrderedDict (내장)
|
|
- **의존성:** BF-5 (area명 통일 선행)
|
|
- **완료 기준:** body에 4개 블록이 세로로 쌓여서 보임 (겹침 없음)
|
|
- **상태:** 코드 수정 완료, md 반영 중
|
|
|
|
### BF-5: 제목 안 보임 (area명 불일치)
|
|
- **파일:** src/design_director.py (LAYOUT_PRESETS)
|
|
- **내용:** 프리셋 4개의 area명 `title` → `header`로 통일 (slide-base.html이 `header` 사용)
|
|
- **기술:** 문자열 교체
|
|
- **의존성:** 없음
|
|
- **완료 기준:** 슬라이드에 제목이 표시됨
|
|
- **상태:** sidebar-right 프리셋 수정 완료, 나머지 3개 확인 필요
|
|
|
|
### BF-6: sidebar 카드 3열 찢어짐
|
|
- **파일:** src/design_director.py (STEP_B_PROMPT)
|
|
- **내용:** 팀장 Step B 프롬프트에 "sidebar zone은 전체 너비의 35%로 좁다. card-grid 배치 시 카드 열 수를 공간에 맞게 판단하라" 추가
|
|
- **기술:** 프롬프트 엔지니어링
|
|
- **의존성:** 없음
|
|
- **완료 기준:** sidebar의 카드가 1열 세로로 배치됨
|
|
- **상태:** 미수정
|
|
|
|
### BF-7: body 블록 텍스트 비어있음 (content_editor 매칭 오류)
|
|
- **파일:** src/content_editor.py
|
|
- **내용:** 같은 area에 여러 블록이 있을 때 첫 번째만 매칭되는 문제. `break` 제거 + area+topic_id로 정확 매칭. 편집자 프롬프트 출력 형식에 `topic_id` 추가.
|
|
- **기술:** Python 조건문 수정
|
|
- **의존성:** 없음
|
|
- **완료 기준:** body의 모든 블록에 텍스트가 채워짐
|
|
- **상태:** 미수정
|
|
|
|
### BF-8: 컨테이너 예산 기반 블록 배치 (프레임 넘침 방지)
|
|
- **파일:** src/design_director.py, templates/catalog.yaml, static/base.css, templates/blocks/visuals/*.html
|
|
- **내용:**
|
|
- 근본 원인: 팀장이 콘텐츠 중심으로 블록 선택 → 높이 고려 없이 body에 4개 블록 쌓음 → 720px 초과 → overflow:hidden으로 잘림
|
|
- 해결: 컨테이너(zone) 크기 예산을 먼저 확인하고, 예산 안에서 블록을 선택하는 사고 순서로 전환
|
|
- LAYOUT_PRESETS: zone별 budget_px + width_pct 추가
|
|
- STEP_B_PROMPT: 4단계 사고 순서 (컨테이너 확인→배정→블록 선택+높이 계산→검증)
|
|
- catalog.yaml: 블록별 height_cost 추가 (compact ~70px / medium ~150px / large ~200px / xlarge ~400px)
|
|
- base.css: area 컨테이너에 overflow:hidden + min-height:0 안전망
|
|
- 시각화 블록 CSS: flex-shrink + responsive SVG
|
|
- **기술:** 프롬프트 엔지니어링 + CSS 안전망
|
|
- **의존성:** 없음
|
|
- **완료 기준:** body 영역 블록이 720px 프레임 안에 모두 보임. 넘침 없음.
|
|
- **한계:** 프롬프트만으로는 Sonnet이 grid를 무시하는 문제를 방지할 수 없음 → BF-9 필요
|
|
|
|
### BF-9: grid와 Sonnet의 역할 분리 (설계 수정)
|
|
- **파일:** src/design_director.py
|
|
- **내용:**
|
|
- 설계 오류: Step B에서 Sonnet에게 grid 값을 출력하라고 요구 → Sonnet이 자기만의 grid를 생성해버림
|
|
- 근본 원인: grid는 코드(Step A)가 결정하는 것인데 Sonnet에게 에코를 요구한 것 자체가 잘못
|
|
- 해결:
|
|
- Step B 프롬프트에서 grid 출력 요구 제거. Sonnet은 `blocks` 배열만 출력
|
|
- `create_layout_concept()`에서 grid 값은 프리셋에서 직접 가져옴 (Sonnet 출력 무시)
|
|
- Sonnet이 출력한 area명이 프리셋 zone에 없으면 가장 가까운 zone으로 코드 매핑
|
|
- 원칙: **코드가 결정한 것은 코드가 유지한다. Sonnet은 콘텐츠 판단만.**
|
|
- **기술:** Python 코드 수정 + 프롬프트 출력 형식 변경
|
|
- **의존성:** BF-8 (프리셋에 zone 정보 필요)
|
|
- **완료 기준:** Sonnet 출력에 grid 값이 없음. 최종 HTML의 grid는 항상 프리셋과 100% 일치.
|
|
|
|
### BF-10: _CATALOG_MAP 캐시 갱신 문제
|
|
- **파일:** src/renderer.py
|
|
- **내용:**
|
|
- 현상: catalog.yaml을 수정해도 서버 재시작 전까지 구 매핑 유지 → _legacy 블록 로드
|
|
- 근본 원인: _CATALOG_MAP이 모듈 레벨 global로 한 번만 로드됨
|
|
- 해결: reload 옵션 (--reload 시 자동 갱신) 또는 매 요청마다 파일 mtime 확인 후 reload
|
|
- **기술:** Python pathlib stat() (내장)
|
|
- **의존성:** 없음
|
|
- **완료 기준:** catalog.yaml 수정 → 서버 재시작 없이 새 매핑 적용
|
|
|
|
### DA-16: 통합 테스트
|
|
- **파일:** tests/test_pipeline.py, tests/test_renderer.py
|
|
- **내용:** 전체 파이프라인 테스트 + 블록 렌더링 테스트
|
|
- **의존성:** BF-2, BF-3, BF-4, BF-5, BF-6, BF-7
|
|
- **완료 기준:** 테스트 전체 통과
|
|
|
|
---
|
|
|
|
---
|
|
|
|
## Phase 5: 블록 라이브러리 확장
|
|
|
|
### DA-17: Figma 에셋 추출 + 블록 템플릿 제작
|
|
- **상태:** done
|
|
- **산출물:**
|
|
- Figma 스크린샷 16장 (`docs/figma-screenshots/`)
|
|
- Figma 에셋 15개+ (`docs/figma-assets/`)
|
|
- 신규 블록 템플릿 6종 (`templates/blocks/` 카테고리별)
|
|
- 디자인 분석 보고서 (`docs/figma-analysis/DESIGN-ANALYSIS.md`)
|
|
- 블록 인덱스 (`templates/blocks/INDEX.md`)
|
|
- **완료 기준:** 신규 블록 6개 독립 렌더링 테스트 통과, Figma 톤 반영
|
|
|
|
### DA-18: 블록 라이브러리 카테고리 재편
|
|
- **상태:** done
|
|
- **내용:** 플랫 구조 → 6개 카테고리 폴더 (headers, cards, tables, visuals, emphasis, media)
|
|
- **완료 기준:** INDEX.md에 전체 구조 정리, 기존 루트 파일 정리
|
|
|
|
### DA-19: 변형 확장
|
|
- **상태:** done (46개 달성)
|
|
- **산출물:** 46개 블록 (6 카테고리), catalog.yaml 46개, BLOCK_SLOTS 46개 동기화
|
|
- **완료 기준:** ✅ 달성
|
|
|
|
---
|
|
|
|
## Phase 2: 파이프라인 고도화 (상세: docs/PHASE2-PLAN.md, PHASE2-PROCESS.md)
|
|
|
|
### P2-A: FAISS 블록 검색 인덱스
|
|
- **파일:** `src/block_search.py` (신규), `scripts/build_block_index.py` (신규), `src/design_director.py` (수정)
|
|
- **내용:** catalog 전문 → FAISS 검색으로 관련 블록 5~8개만 프롬프트에 전달
|
|
- **기술:** BAAI/bge-m3 + faiss-cpu (Kei persona와 동일 패턴)
|
|
- **의존성:** 없음
|
|
- **완료 기준:** 꼭지별 검색 → 카테고리별 최소 1개 보장 → 프롬프트 토큰 절약
|
|
|
|
### P2-B: SVG N개 자동 배치
|
|
- **파일:** `src/svg_calculator.py` (신규), `src/renderer.py` (수정), `templates/blocks/visuals/venn-diagram.html` (수정)
|
|
- **내용:** venn-diagram 3개 고정 → N개(2~7) cos/sin 자동 계산
|
|
- **기술:** Python math (내장, 추가 의존성 없음)
|
|
- **의존성:** 없음 (2-A와 병렬 가능)
|
|
- **완료 기준:** N=2~7 각각 렌더링 테스트 통과. Phase 1 fallback 유지.
|
|
|
|
### P2-C: Step A Opus+FAISS 고도화
|
|
- **파일:** `src/design_director.py` (수정)
|
|
- **내용:** 규칙 4줄 → Opus(Kei API)가 FAISS 후보에서 블록 선정 + 배치 결정
|
|
- **기술:** Kei API 호출 (Opus). anthropic 직접 호출 **절대 금지**.
|
|
- **의존성:** P2-A 완료 필수
|
|
- **완료 기준:** Opus가 콘텐츠 보고 블록 후보 선정. Kei API 실패 시 기존 방식 fallback.
|
|
|
|
### P2-D: 5단계 재검토 강화
|
|
- **파일:** `src/pipeline.py` (수정)
|
|
- **내용:** shrink/rewrite action 구현 + 재조정 루프 (MAX=2)
|
|
- **기술:** Anthropic API (Sonnet) — 기존 패턴
|
|
- **의존성:** 없음 (병렬 가능)
|
|
- **완료 기준:** expand/shrink/rewrite 3개 action 모두 동작. 루프 2회 제한.
|
|
|
|
### P2-E: 누락 기능
|
|
- **E-1 Pillow:** `src/design_director.py` — 이미지 크기 읽기 → 블록 선택 참고
|
|
- **E-2 details-block:** `src/design_director.py` + `src/pipeline.py` — detail_target → details-block 배치
|
|
- **의존성:** 없음 (병렬 가능)
|
|
- **완료 기준:** 이미지 크기 정보가 팀장에게 전달. details 접기/펼치기 동작.
|
|
|
|
### 의존 관계
|
|
```
|
|
P2-A (FAISS) ──────────────────────┐
|
|
├→ P2-C (Opus+FAISS)
|
|
P2-B (SVG N개) ── 병렬 │
|
|
P2-D (재검토) ─── 병렬 │
|
|
P2-E (누락기능) ── 병렬 │
|
|
```
|
|
|
|
### DA-21: renderer 카테고리 경로 지원
|
|
- **상태:** todo
|
|
- **내용:** `renderer.py`의 블록 로드 경로를 `blocks/{type}.html` → `blocks/{category}/{name}.html`로 변경
|
|
- **주의:** 기존 파이프라인과 호환성 유지
|
|
- **의존성:** DA-18
|
|
- **완료 기준:** 카테고리 경로로 블록 렌더링 정상 동작
|
|
|
|
### DA-22: catalog.yaml 경로 업데이트
|
|
- **상태:** todo
|
|
- **내용:** template 경로를 새 폴더 구조로 반영
|
|
- **의존성:** DA-21
|
|
- **완료 기준:** catalog.yaml의 모든 template 경로가 실제 파일과 일치
|
|
|
|
---
|
|
|
|
## Phase V: 콘텐츠-컨테이너 적합성 검증 + Kei 에스컬레이션 (상세: PHASE-V.md)
|
|
|
|
> 근거: Phase T' 디버깅에서 발견된 구조적 결함. 콘텐츠 분량과 무관한 컨테이너 고정 배분, 적합성 검증 부재, 판단 주체 부재.
|
|
|
|
### V-1: Stage 1.7 수정 — 꼭지별 블록 선택
|
|
- **현재:** 영역당 블록 1개 → **변경:** 꼭지당 블록 1개
|
|
- **파일:** `src/block_reference.py`, `src/pipeline.py`
|
|
- **의존성:** 없음
|
|
- **완료 기준:** 배경 꼭지2개 → 블록2개 선택
|
|
|
|
### V-2: Stage 1.8 신규 — 적합성 검증
|
|
- **파일:** `src/fit_verifier.py` (신규)
|
|
- **내용:** 꼭지별 필요 높이 계산 → 컨테이너 배분 → 들어가는지 검증
|
|
- **의존성:** V-1
|
|
- **완료 기준:** 배경 117px 부족 자동 감지
|
|
|
|
### V-3: Stage 1.8 재배분 로직
|
|
- **파일:** `src/fit_verifier.py`
|
|
- **내용:** 여유 영역 → 부족 영역으로 공간 재분배
|
|
- **의존성:** V-2
|
|
- **완료 기준:** 배경 117→151px, 본심 345→311px 자동 재배분
|
|
|
|
### V-4: Stage 1.8 Kei 에스컬레이션
|
|
- **파일:** `src/fit_verifier.py`, `src/kei_client.py`
|
|
- **내용:** 재배분으로도 안 될 때 AI가 옵션 생성 → Kei에게 결정 요청
|
|
- **의존성:** V-2, V-3
|
|
- **완료 기준:** Kei에게 옵션 전달 → 결정 수신 → 파이프라인 계속
|
|
|
|
### V-5: Stage 1.5a 리팩터
|
|
- **파일:** `src/space_allocator.py`, `src/pipeline.py`
|
|
- **내용:** weight 고정 배분 → 콘텐츠 분량 기반 동적 배분으로 교체
|
|
- **의존성:** V-2
|
|
- **완료 기준:** weight 하드코딩 제거
|
|
|
|
### V-6: 통합 검증 — ✅ 완료 (31/31 통과, 하드코딩 0개)
|
|
|
|
### V-7: 주종 관계 블록 내 종속 꼭지 처리
|
|
- **파일:** `src/fit_verifier.py`, `src/block_reference.py`
|
|
- **내용:** 종속 꼭지 분량에 따라 인라인/하위블록/보조블록 자동 판단 → Kei 확인
|
|
- **완료 기준:** 배경 꼭지2(supporting)가 꼭지1 블록 안에 인라인
|
|
|
|
### V-8: 여유 공간 콘텐츠 보충
|
|
- **파일:** `src/fit_verifier.py`
|
|
- **내용:** 재배분 후 여유 감지 → 관련 팝업 구조화 콘텐츠 → 요약 블록 추가 제안 → Kei 확인
|
|
- **완료 기준:** 본심 여유 공간에 비교표 핵심 요약 배치
|
|
|
|
### V-9: 영역 핵심 결론 강조 블록
|
|
- **파일:** `src/fit_verifier.py`, `src/block_reference.py`
|
|
- **내용:** purpose에서 핵심 결론 추출 → 강조 블록 제안 → Kei 확인
|
|
- **완료 기준:** 배경 "체계적 정립 필요"가 강조 블록으로 표시
|
|
|
|
### V-10: 텍스트 핵심 키워드 bold
|
|
- **파일:** `src/html_generator.py`
|
|
- **내용:** source_data 핵심 키워드 추출 → Stage 2 프롬프트에 전달 → Sonnet이 bold 처리
|
|
- **완료 기준:** 본심 "상위개념", "기술융합" 등 핵심 키워드 bold
|
|
|
|
---
|
|
|
|
## Phase Y: MDX 외부 컴포넌트 인라인 삽입
|
|
|
|
> 근거: MDX에서 `import ... from '*.astro'`로 불러오는 외부 컴포넌트(표, 다이어그램 등)가 파이프라인에서 누락됨. import문은 제거되고 `<DxEffect />` 같은 태그는 사라져서 콘텐츠 손실 발생.
|
|
|
|
### Y-1: import문 파싱 — 컴포넌트명:파일경로 매핑
|
|
- **파일:** `src/mdx_normalizer.py`
|
|
- **내용:** `import Foo from '../../components/foo.astro'` → `{"Foo": 절대경로}` 매핑 추출
|
|
- **의존성:** base_path (MDX 원본 파일 위치, pipeline.py에서 전달)
|
|
- **완료 기준:** import문에서 컴포넌트명→절대경로 dict 반환
|
|
|
|
### Y-2: .astro 파일 파싱 — HTML + CSS 추출
|
|
- **파일:** `src/mdx_normalizer.py`
|
|
- **내용:** .astro 파일에서 `---` frontmatter 제거, HTML 본문 + `<style>` 블록 추출
|
|
- **의존성:** Y-1
|
|
- **완료 기준:** dx.astro → `<div class="table-wrapper">...</div>` + `<style>...</style>` 반환
|
|
|
|
### Y-3: 셀프클로징 태그 교체 — 인라인 삽입
|
|
- **파일:** `src/mdx_normalizer.py`
|
|
- **내용:** `<DxEffect />` 태그를 Y-2에서 추출한 HTML+CSS로 교체
|
|
- **의존성:** Y-1, Y-2
|
|
- **완료 기준:** MDX 정규화 결과에 외부 컴포넌트 HTML이 인라인으로 포함
|
|
|
|
### Y-4: Astro 특수 문법 정리
|
|
- **파일:** `src/mdx_normalizer.py`
|
|
- **내용:** Astro의 멀티라인 태그(`<td class="category-cell">텍스트</td>` 줄바꿈 패턴), `style="letter-spacing: -0.9px"` 등 인라인 스타일 정리
|
|
- **의존성:** Y-2
|
|
- **완료 기준:** 추출된 HTML이 브라우저에서 정상 렌더링
|
|
|
|
---
|
|
|
|
## 의존 관계
|
|
|
|
```
|
|
Phase 1~2 (기반+블록):
|
|
DA-1 → DA-2, DA-3 → DA-4~DA-10 → DA-11(렌더러)
|
|
|
|
Phase 3 (AI 파이프라인):
|
|
DA-12(실장) → DA-13(팀장) → DA-13b(편집자) → DA-14(조립+재검토)
|
|
|
|
Phase 4 (UI):
|
|
DA-14 → DA-15(프론트엔드) → DA-16(테스트)
|
|
|
|
Phase 5 (블록 라이브러리):
|
|
DA-17(Figma추출) → DA-18(카테고리재편) → DA-19(변형확장) → DA-20(FAISS)
|
|
DA-18 → DA-21(renderer경로) → DA-22(catalog경로)
|
|
|
|
Phase V (적합성 검증):
|
|
V-1(꼭지별블록) → V-2(적합성검증) → V-3(재배분) → V-4(Kei에스컬레이션)
|
|
V-2 → V-5(1.5a리팩터)
|
|
V-1~V-5 → V-6(통합검증)
|
|
```
|
|
|
|
- Phase 1~2, 5: AI 없이 진행 가능
|
|
- Phase 3: Anthropic API 필요 (5단계 파이프라인)
|
|
- Phase 5는 Phase 3와 **병렬** 진행 가능
|
|
|
|
---
|
|
|
|
## Phase Z: 매칭 시스템 통합 (2026-04-28 ~)
|
|
|
|
> **상세 설계**: [IMPROVEMENT-REDESIGN.md](IMPROVEMENT-REDESIGN.md)
|
|
>
|
|
> 별도 검증된 매칭 시스템 (V1~V4, `tests/matching/`) 을 기존 pipeline 에 통합.
|
|
|
|
### 단계적 진행
|
|
|
|
| 단계 | 내용 | 산출물 |
|
|
|---|---|---|
|
|
| **Phase Z-1** | 통합 prototype — Stage 1.7 (블록 선택) 만 V4 로 교체 | MDX 03 회귀 통과 |
|
|
| **Phase Z-2** | 매칭 + 4 프리셋 (Type A/B/B'/B'') 통합 | MDX 03/02/01 자동 매칭 |
|
|
| **Phase Z-3** | 컨테이너 검증 + 5 차 Fallback | 안정적 자동 처리 |
|
|
| **Phase Z-4** | 전체 통합 + 회귀 검증 | 새 pipeline 완성 |
|
|
|
|
### 사전 결정 사항 (검토 완료)
|
|
|
|
- **위계** : slide → slide-base → slide-body → 레이아웃 → Zone → 프레임
|
|
- **5 단계 흐름** : MDX 분석/레이아웃 → Zone 텍스트 배치 → 프레임 매칭 → 검토 → 출력
|
|
- **매칭 분기** : 완벽 / 어정쩡 / 안 됨 → 후속 작업 차등
|
|
- **레이아웃 프리셋** : Type A / B / B' / B'' (기존 4 가지 활용)
|
|
- **절대 룰** : 텍스트 원문 무손실, 자유 디자인 금지, MDX 1 = 슬라이드 1
|
|
|
|
### 사전 작업 진행 상태
|
|
|
|
✅ **완료** (2026-04-28)
|
|
- 32 frame Zone 적용 분류 (`zone_direct` / `zone_adapt` / `zone_extract` / `reference_only`) — [docs/architecture/FRAME-INTEGRATION-MAP.md](docs/architecture/FRAME-INTEGRATION-MAP.md)
|
|
- Frame / Style Inventory (32 frame + 18 token + 6 legacy) — [docs/architecture/PHASE-Z-FRAME-STYLE-INVENTORY.md](docs/architecture/PHASE-Z-FRAME-STYLE-INVENTORY.md)
|
|
|
|
⬜ **미진행**
|
|
- catalog / runtime 설계 prep
|
|
- slide-base 검증
|
|
|
|
⚠️ **미실행 / 의도적으로 보류** (승인 전)
|
|
- 기존 `templates/blocks/` 삭제 / 교체
|
|
- catalog / runtime 구현
|
|
- `templates/styles/frame-patterns/` 신규 파일 생성
|
|
- 새 token (`gap_candidate`) 추가
|
|
- legacy structures 6 파일 삭제
|
|
|
|
> ⚠️ **Phase Z-1 자체는 진행 중**. 위 ✅ 는 *사전 작업 중 일부* 완료 표시.
|
|
|
|
---
|
|
|
|
## 기술 스택
|
|
|
|
| 역할 | 도구 | 비고 |
|
|
|------|------|------|
|
|
| 서버 | FastAPI + uvicorn | 포트 8001 |
|
|
| 템플릿 엔진 | Jinja2 | 카테고리별 블록 조합 |
|
|
| 렌더링 | CSS Grid + 디자인 토큰 | 슬라이드 + 웹 |
|
|
| 한국어 폰트 | Pretendard Variable | word-break: keep-all |
|
|
| AI (5단계) | Anthropic API (Sonnet) | 실장→팀장→편집자→실무자→재검토 |
|
|
| 이미지 생성 | Gemini API | 복합 시각화 배경 (레이어 방식) |
|
|
| Figma | Figma REST API + Framelink MCP | 에셋 추출 |
|
|
| 변형 검색 | FAISS (향후) | 블록 40개+ 시 |
|
|
| 테스트 | pytest | 렌더링 + 파이프라인 |
|