문서 정리: 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:
605
docs/history/IMPROVEMENT-PHASE-M.md
Normal file
605
docs/history/IMPROVEMENT-PHASE-M.md
Normal file
@@ -0,0 +1,605 @@
|
||||
# Phase M: 비중 시스템 + 역할-블록 매핑 + 블록 안전성 + 원본 보존
|
||||
|
||||
> 상태: ✅ 완료 — Kei 비중 시스템 구축. Phase O에서 컨테이너 시스템으로 발전.
|
||||
>
|
||||
> Phase I~L에서 코드 정합성, 블록 선택 권한, 프롬프트 원칙, 렌더링 측정을 다뤘지만
|
||||
> **근본 문제가 해결되지 않음: "이 페이지의 본심이 뭔지" 판단이 없음.**
|
||||
> Kei가 콘텐츠마다 본심/배경/첨부/결론을 판단하고, 비중(weight)을 결정해야 함.
|
||||
> 코드 상수(하드코딩)가 아닌 **Kei의 매번 판단**.
|
||||
>
|
||||
> **후속 변경 (Phase O):**
|
||||
> - pipeline.py의 Phase M 공간 할당 코드 → Phase O `calculate_container_specs()`로 교체
|
||||
> - `PURPOSE_WEIGHT` 상수 → 삭제 (Kei weight 직접 사용)
|
||||
> - `allocate_height_budget()` → `calculate_container_specs()` + `finalize_block_specs()`로 교체
|
||||
|
||||
---
|
||||
|
||||
## 문제점 전체 리스트 (9건)
|
||||
|
||||
### P-1: 비중(weight) 개념 부재
|
||||
|
||||
**현상:** Kei가 꼭지 5개를 분류하면, 팀장이 5개를 동등하게 1:1 배치. "본심이 60%, 배경이 15%"라는 공간 비중 개념이 파이프라인 어디에도 없음.
|
||||
|
||||
**예시:** DX vs BIM 비교(본심)와 용어 정의(첨부)가 동일한 크기의 블록을 받음.
|
||||
|
||||
**영향:** 핵심 메시지가 묻히고, 보조 정보가 과도한 공간 차지.
|
||||
|
||||
**위치:** 1단계(Kei) 출력 → 2단계(팀장) 입력 사이.
|
||||
|
||||
**Phase I~L에서 한 것:** Phase K에서 PURPOSE_WEIGHT 상수 추가, Phase L에서 allocate_height_budget() 함수 추가.
|
||||
**문제:** 하드코딩된 고정 비율. 콘텐츠마다 다른데 코드가 일괄 적용.
|
||||
|
||||
---
|
||||
|
||||
### P-2: 편집자적 구조 판단 부재
|
||||
|
||||
**현상:** Kei가 꼭지를 "나열"만 함. 아래와 같은 편집 구조를 잡지 못함:
|
||||
|
||||
```
|
||||
(배경/목적) 왜 이 페이지가 필요한가
|
||||
(본심) 이 페이지가 말하려는 핵심
|
||||
(첨부) 본심을 이해하기 위한 보조 정보
|
||||
(잊지마) 절대 잊으면 안 되는 결론
|
||||
```
|
||||
|
||||
**현재:** purpose와 layer가 있지만 "이 페이지의 본심은 꼭지2이고 나머지는 보조다"라는 판단이 없음.
|
||||
|
||||
**영향:** 모든 꼭지가 동등하게 취급됨. 스토리라인은 있으나 강약이 없음.
|
||||
|
||||
**위치:** 1단계 KEI_PROMPT.
|
||||
|
||||
**Phase I~L에서 한 것:** Phase K에서 인지 흐름 원칙 추가.
|
||||
**문제:** 원칙만 줬지 Kei 출력 스키마에 "본심/배경/첨부/결론" 구분이 없음.
|
||||
|
||||
---
|
||||
|
||||
### P-3: 블록 선택이 "콘텐츠 역할"이 아닌 "데이터 타입"으로 결정됨
|
||||
|
||||
**현상:** 팀장(Sonnet)이 블록을 고를 때 "텍스트 → 텍스트 블록, 표 → 표 블록"으로 데이터 형식만 보고 선택. "이것이 본심이니까 정보 밀도 높은 블록" 판단 안 함.
|
||||
|
||||
**올바른 선택 기준:**
|
||||
```
|
||||
본심(핵심전달) → 정보형 블록 (compare-2col-split 등) → 공간 최대
|
||||
배경(문제제기) → 컴팩트 블록 (topic-left-right 등) → 공간 최소
|
||||
첨부(용어정의) → 참조형 블록 (card-numbered 등) → sidebar
|
||||
결론(강조) → 선언형 블록 (banner-gradient) → footer
|
||||
```
|
||||
|
||||
**위치:** 2단계 STEP_B_PROMPT + FAISS 검색.
|
||||
|
||||
**Phase I~L에서 한 것:** Phase K에서 purpose별 허용/금지 블록 규칙 추가.
|
||||
**문제:** purpose 기반이지 "본심/배경" 기반이 아님. Kei가 비중을 출력해야 팀장이 비중대로 블록 크기 결정.
|
||||
|
||||
---
|
||||
|
||||
### P-4: 공간 배분 로직 부재
|
||||
|
||||
**현상:** 팀장이 zone별 height_cost만 검증하고, "이 꼭지에 몇 px를 줘야 하는가"는 계산하지 않음.
|
||||
|
||||
**현재 로직:** 블록 선택 → height_cost 합산 확인 → 초과하면 교체
|
||||
**필요한 로직:** 비중(weight) 확인 → weight에 따라 zone 예산 배분 → 배분된 px에 맞는 블록 선택
|
||||
|
||||
**위치:** 2단계 create_layout_concept().
|
||||
|
||||
**Phase I~L에서 한 것:** Phase L에서 allocate_height_budget() + max-height CSS 적용.
|
||||
**문제:** PURPOSE_WEIGHT가 하드코딩. Kei가 판단한 weight를 사용해야 함.
|
||||
|
||||
---
|
||||
|
||||
### P-5: Figma 비추출 블록 사용
|
||||
|
||||
**현상:** 38개 블록 중 9개가 Figma 디자인 없이 코드로 만든 블록. 디자인 품질 미검증.
|
||||
|
||||
**비-Figma 블록 (9개):**
|
||||
- topic-numbered, card-numbered, table-simple-striped
|
||||
- venn-diagram, process-horizontal
|
||||
- comparison-2col, callout-warning
|
||||
- divider-text, image-before-after
|
||||
|
||||
**영향:** 시각적 통일성 저하.
|
||||
|
||||
**위치:** 2단계 블록 선택 시 필터링 없음.
|
||||
|
||||
**Phase I~L에서 한 것:** 안 다룸.
|
||||
|
||||
---
|
||||
|
||||
### P-6: 블록-zone 적합성 검증 부재
|
||||
|
||||
**현상:** sidebar(35%)에 full-width 전용 블록을 배치하면 찌그러짐. 블록이 어떤 zone에서 작동하는지 검증 없음.
|
||||
|
||||
**full-width 전용 블록 (15개):**
|
||||
- card-icon-desc, card-compare-3col, comparison-2col
|
||||
- topic-left-right, compare-pill-pair, process-horizontal 등
|
||||
|
||||
**영향:** sidebar에서 블록 깨짐, 텍스트 한 글자씩 줄바꿈.
|
||||
|
||||
**위치:** 2단계 블록 선택 후 검증.
|
||||
|
||||
**Phase I~L에서 한 것:** Phase J에서 sidebar 1열 강제(column_override). 불완전.
|
||||
|
||||
---
|
||||
|
||||
### P-7: 블록별 글자 수용량 미정의
|
||||
|
||||
**현상:** 블록에 텍스트를 넣을 때 "얼마나 들어가는지" 기준 없음. char_guide 참고하지만 실제 렌더링과 괴리.
|
||||
|
||||
**결과:** 텍스트 과다 → overflow / 텍스트 과소 → 빈 페이지.
|
||||
|
||||
**위치:** catalog.yaml에 schema 미정의. 3단계 편집자 프롬프트.
|
||||
|
||||
**Phase I~L에서 한 것:** Phase I에서 slot_desc 추가, Phase K에서 분량 가이드라인 추가. 실제 수용량은 미정의.
|
||||
|
||||
---
|
||||
|
||||
### P-8: 내부 스크롤 미감지
|
||||
|
||||
**현상:** 5단계 검수에서 area 레벨 overflow만 체크. 블록 내부의 overflow: auto/hidden으로 인한 내부 스크롤/잘림은 감지 못함.
|
||||
|
||||
**예시:** compare-3col-badge는 overflow: auto여서 area는 OK인데 블록 안에서 스크롤 발생.
|
||||
|
||||
**영향:** "검증 통과"했는데 실제로는 내용 잘림.
|
||||
|
||||
**위치:** 5단계 검수.
|
||||
|
||||
**Phase I~L에서 한 것:** Phase L에서 Selenium 측정 추가. 하지만 블록 내부 overflow까지 체크하는지 미확인.
|
||||
|
||||
---
|
||||
|
||||
### P-9: 원본 텍스트 임의 재작성
|
||||
|
||||
**현상:** 3단계 편집자가 원본을 "편집"이 아닌 "재작성". 원본 문구, 출처, 수치 변경/누락.
|
||||
|
||||
**영향:** 정보 정확도 저하, 출처 누락.
|
||||
|
||||
**위치:** 3단계 편집자 프롬프트 + Kei API 응답 품질.
|
||||
|
||||
**Phase I~L에서 한 것:** Phase J에서 source 슬롯 규칙 추가, EDITOR_PROMPT에 보존 원칙. 강제력 부족.
|
||||
|
||||
---
|
||||
|
||||
## 개선 방향 (4가지)
|
||||
|
||||
### 방향 1: 비중(weight) 시스템 — P-1, P-2, P-4 해결 [긴급]
|
||||
|
||||
**핵심:** Kei가 콘텐츠마다 본심/배경/첨부/결론을 판단하고 weight를 출력.
|
||||
|
||||
**KEI_PROMPT 출력 스키마 변경:**
|
||||
```json
|
||||
{
|
||||
"title": "건설산업 DX의 올바른 이해",
|
||||
"core_message": "BIM은 DX의 기초적 일부분이다",
|
||||
"page_structure": {
|
||||
"본심": {"topic_ids": [2, 3], "weight": 0.60},
|
||||
"배경": {"topic_ids": [1], "weight": 0.15},
|
||||
"첨부": {"topic_ids": [4], "weight": 0.15},
|
||||
"결론": {"topic_ids": [5], "weight": 0.10}
|
||||
},
|
||||
"topics": [...]
|
||||
}
|
||||
```
|
||||
|
||||
**파이프라인 반영:**
|
||||
- 1단계: Kei가 page_structure + weight 출력 (콘텐츠마다 다름, 하드코딩 아님)
|
||||
- 2단계: weight → px 변환 (body 490px × 0.6 = 294px → 본심)
|
||||
- 2단계: 배분된 px에 맞는 블록 선택
|
||||
- 배치: 본심 비중이 결정하면 가로/세로/구조화 방식도 자연스럽게 따라옴
|
||||
- Phase L의 PURPOSE_WEIGHT 하드코딩 제거 → Kei 출력 weight 사용
|
||||
|
||||
---
|
||||
|
||||
### 방향 2: 역할-블록 매핑 체계 — P-3 해결 [중요]
|
||||
|
||||
**콘텐츠 역할 × 콘텐츠 성격 → 블록 결정:**
|
||||
|
||||
```
|
||||
본심 + 비교 → compare-2col-split, compare-3col-badge
|
||||
본심 + 구조 → keyword-circle-row, card-step-vertical
|
||||
본심 + 정의 → card-numbered (large), dark-bullet-list (large)
|
||||
배경 + 문제 → topic-left-right (compact), quote-question (compact)
|
||||
배경 + 사례 → callout-warning (compact), quote-big-mark (compact)
|
||||
첨부 + 정의 → card-numbered (sidebar), dark-bullet-list (sidebar)
|
||||
결론 → banner-gradient (footer)
|
||||
```
|
||||
|
||||
**반영 위치:** STEP_B_PROMPT — 현재 purpose별 허용/금지를 "역할 × 성격" 매트릭스로 확장.
|
||||
|
||||
---
|
||||
|
||||
### 방향 3: 블록 안전성 인프라 — P-5, P-6, P-7, P-8 해결 [중요]
|
||||
|
||||
| 항목 | 내용 | 해결 방법 |
|
||||
|------|------|----------|
|
||||
| P-5 Figma 블록 필터 | 비-Figma 9개 블록 식별 | 블록 선택 시 Figma 블록 우선 또는 비-Figma 경고 |
|
||||
| P-6 블록-zone 적합성 | full-width 15개 블록 식별 | zone별 허용 블록 맵 (코드 검증) |
|
||||
| P-7 글자 수용량 | 블록별 max chars | catalog.yaml에 zone별 max_chars 추가 |
|
||||
| P-8 내부 스크롤 | 블록 내부 overflow 감지 | Selenium 측정 시 블록 내부까지 scrollHeight 체크 |
|
||||
|
||||
---
|
||||
|
||||
### 방향 4: 원본 보존 강화 — P-9 해결 [보통]
|
||||
|
||||
**3단계 편집자에게 source_text 직접 전달:**
|
||||
- 현재: 원본 콘텐츠 전체를 주고 "여기서 가져와라"
|
||||
- 변경: 각 꼭지별로 Kei가 source_hint에 명시한 원본 텍스트를 **직접 추출하여** 편집자에게 전달
|
||||
- "이 텍스트에서 추출하라. 새로 쓰지 마라. 축약만 허용."
|
||||
|
||||
---
|
||||
|
||||
## 우선순위
|
||||
|
||||
```
|
||||
[긴급] P-1 + P-2 + P-4 → 방향 1: 비중 시스템
|
||||
← 이것이 없으면 나머지를 해도 의미 없음
|
||||
← Kei가 판단. 하드코딩 아님.
|
||||
← 비중이 결정되면 배치, 블록 크기, 가로/세로 흐름이 자동으로 따라옴
|
||||
|
||||
[중요] P-3 → 방향 2: 역할-블록 매핑
|
||||
← 비중 시스템 위에서 역할별 블록 정확 매칭
|
||||
|
||||
[중요] P-7 + P-8 → 방향 3-a: 스키마 + 검증
|
||||
← 글자 수용량 정의 + 내부 overflow 감지
|
||||
|
||||
[보통] P-5 + P-6 → 방향 3-b: 필터링
|
||||
← Figma 블록 우선 + zone 적합성 검증
|
||||
|
||||
[보통] P-9 → 방향 4: 편집자 원본 보존
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase I~L과의 관계
|
||||
|
||||
| 기존 Phase | Phase M에서 변경 |
|
||||
|-----------|----------------|
|
||||
| Phase K PURPOSE_WEIGHT 하드코딩 | **제거** → Kei 출력 weight 사용 |
|
||||
| Phase K purpose 가이드 | **유지** + 역할×성격 매트릭스로 확장 |
|
||||
| Phase L allocate_height_budget() | **유지** + 입력을 PURPOSE_WEIGHT 대신 Kei weight로 변경 |
|
||||
| Phase L measure_rendered_heights() | **유지** + 블록 내부 overflow 체크 추가 (P-8) |
|
||||
| Phase L calculate_trim_chars() | **유지** |
|
||||
| Phase J Opus 존중 규칙 | **유지** |
|
||||
| Phase J Kei 최종 검수 | **유지** + 비중 기반 검수 항목 추가 |
|
||||
| Phase I slot_desc | **유지** |
|
||||
| Phase I SSE 공통 유틸 | **유지** |
|
||||
|
||||
**회귀 없음.** 기존 인프라(측정, 계산, 검수) 위에 비중 시스템을 추가.
|
||||
**제거 대상:** PURPOSE_WEIGHT 하드코딩 상수만.
|
||||
|
||||
---
|
||||
|
||||
## 실행 순서
|
||||
|
||||
### M-Step 1: Kei 비중 시스템 (P-1 + P-2 + P-4) [긴급]
|
||||
|
||||
1. KEI_PROMPT 출력 스키마에 page_structure 추가
|
||||
2. Kei가 본심/배경/첨부/결론 + weight를 출력하도록 프롬프트 수정
|
||||
3. pipeline.py에서 Kei 출력의 weight를 읽어서 allocate_height_budget()에 전달
|
||||
4. PURPOSE_WEIGHT 하드코딩 제거
|
||||
5. STEP_B_PROMPT에 weight 기반 블록 크기 지시 추가
|
||||
|
||||
### M-Step 2: 역할-블록 매핑 (P-3)
|
||||
|
||||
6. STEP_B_PROMPT purpose 가이드를 역할×성격 매트릭스로 재구성
|
||||
7. Kei 출력의 relation_type + 역할(본심/배경/첨부)로 블록 결정
|
||||
|
||||
### M-Step 3: 블록 안전성 (P-5 + P-6 + P-7 + P-8)
|
||||
|
||||
8. P-5: catalog.yaml에 figma_source 필드 추가 (Figma 블록 식별)
|
||||
9. P-6: 블록-zone 적합성 맵 정의 + 코드 검증 추가
|
||||
10. P-7: catalog.yaml에 zone별 max_chars 추가
|
||||
11. P-8: slide_measurer.py에서 블록 내부 overflow까지 체크
|
||||
|
||||
### M-Step 4: 원본 보존 (P-9)
|
||||
|
||||
12. 편집자에게 꼭지별 source_text 직접 전달
|
||||
13. "추출만. 재작성 금지." 강화
|
||||
|
||||
---
|
||||
|
||||
## 기술 조사 결과
|
||||
|
||||
### M-Step 1에 필요한 것
|
||||
|
||||
| 항목 | 현재 | 변경 | 도구 |
|
||||
|------|------|------|------|
|
||||
| KEI_PROMPT 출력 | topics만 | + page_structure (본심/배경/첨부/결론 + weight) | 프롬프트 수정 |
|
||||
| page_structure 파싱 | 없음 | `analysis.get("page_structure")` | 코드 추가 |
|
||||
| PURPOSE_WEIGHT 상수 | 하드코딩 (space_allocator.py) | **제거** → Kei weight 사용 | 코드 수정 |
|
||||
| allocate_height_budget() | PURPOSE_WEIGHT 참조 | weight_override 파라미터 추가 | 함수 시그니처 변경 |
|
||||
| STEP_B_PROMPT | purpose별 규칙만 | + weight 기반 블록 크기 지시 | 프롬프트 수정 |
|
||||
|
||||
**충돌:** 없음. page_structure는 새 필드. PURPOSE_WEIGHT 제거는 개선.
|
||||
**Kei vs Sonnet:** Kei가 weight 판단. Sonnet은 weight를 **받아서** 블록 크기 결정.
|
||||
|
||||
---
|
||||
|
||||
### M-Step 2에 필요한 것
|
||||
|
||||
| 항목 | 현재 | 변경 | 도구 |
|
||||
|------|------|------|------|
|
||||
| FAISS 쿼리 | title+summary+role+layer | + purpose + relation_type + expression_hint | block_search.py `_build_query()` 수정 |
|
||||
| STEP_B_PROMPT 가이드 | purpose 6종 허용/금지 | 역할(본심/배경/첨부) × 성격(비교/정의/구조) 매트릭스 | 프롬프트 확장 |
|
||||
|
||||
**충돌:** Phase K purpose 가이드 **위에** 매트릭스 확장. 기존 규칙 유지.
|
||||
|
||||
---
|
||||
|
||||
### M-Step 3에 필요한 것
|
||||
|
||||
| 항목 | 현재 | 변경 | 도구 |
|
||||
|------|------|------|------|
|
||||
| P-5 Figma 식별 | 구분 없음 | catalog.yaml에 `figma_source` 필드 | YAML 수정 |
|
||||
| P-6 zone 적합성 | sidebar 1열만 (J-6) | **블록-zone 적합성 맵** 코드 검증 | 신규 상수 + 검증 로직 |
|
||||
| P-7 글자 수용량 | slot_desc 의미만 | catalog.yaml에 **zone별 max_chars** | YAML + 편집자 연동 |
|
||||
| P-8 내부 overflow | zone 레벨만 측정 | **블록 내부** scrollHeight 체크 | slide_measurer.py JS 확인 |
|
||||
|
||||
**P-6 블록-zone 적합성 맵:**
|
||||
```python
|
||||
# 신규 상수 (design_director.py 또는 별도 모듈)
|
||||
SIDEBAR_SAFE_BLOCKS = {
|
||||
"card-numbered", "card-step-vertical",
|
||||
"banner-gradient", "callout-solution", "callout-warning",
|
||||
"dark-bullet-list", "divider-text", "highlight-strip",
|
||||
"quote-question", "tab-label-row",
|
||||
"topic-left-right", "topic-numbered",
|
||||
"table-simple-striped", "process-horizontal",
|
||||
"image-before-after", "image-grid-2x2", "image-row-2col",
|
||||
}
|
||||
|
||||
FULL_WIDTH_ONLY_BLOCKS = {
|
||||
"card-compare-3col", "card-dark-overlay", "card-icon-desc",
|
||||
"card-image-3col", "card-image-round", "card-stat-number", "card-tag-image",
|
||||
"section-title-with-bg", "section-header-bar", "topic-center",
|
||||
"quote-big-mark", "image-full-caption",
|
||||
"compare-2col-split", "compare-pill-pair", "comparison-2col",
|
||||
}
|
||||
```
|
||||
|
||||
**충돌:** Phase J의 sidebar 1열 강제와 **보완 관계.** J-6은 열 수 제한, M-Step 3은 블록 자체 제한.
|
||||
|
||||
---
|
||||
|
||||
### M-Step 4에 필요한 것
|
||||
|
||||
| 항목 | 현재 | 변경 | 도구 |
|
||||
|------|------|------|------|
|
||||
| 원본 전달 | 전체 content 한 번에 | **토픽별 source_text 추출하여 전달** | fill_content() 수정 |
|
||||
| source_hint | 정의됨, 사용 안 됨 | **편집자에게 전달** | 프롬프트 수정 |
|
||||
| source_data | 텍스트 설명만 | **실제 원본 텍스트 추출 참조** | 코드 추가 |
|
||||
| 재작성 방지 | "보존" 원칙만 | **"추출만. 재작성 금지."** 절대 규칙 | 프롬프트 강화 |
|
||||
|
||||
**충돌:** Phase J source 규칙 **유지 + 보강.**
|
||||
|
||||
---
|
||||
|
||||
## 실행 방안 상세
|
||||
|
||||
### M-Step 1: Kei 비중 시스템
|
||||
|
||||
#### M-1a: KEI_PROMPT 출력 스키마 변경
|
||||
|
||||
**위치:** `src/kei_client.py` KEI_PROMPT (20~79행)
|
||||
|
||||
**추가할 출력 필드:**
|
||||
```json
|
||||
{
|
||||
"title": "...",
|
||||
"core_message": "...",
|
||||
"page_structure": {
|
||||
"본심": {"topic_ids": [2, 3], "weight": 0.60},
|
||||
"배경": {"topic_ids": [1], "weight": 0.15},
|
||||
"첨부": {"topic_ids": [4], "weight": 0.15},
|
||||
"결론": {"topic_ids": [5], "weight": 0.10}
|
||||
},
|
||||
"topics": [...]
|
||||
}
|
||||
```
|
||||
|
||||
**프롬프트에 추가할 지시:**
|
||||
```
|
||||
## 4단계: 페이지 구조 판단
|
||||
콘텐츠를 분석하여 이 페이지의 구조를 판단하라:
|
||||
- **본심**: 이 페이지가 말하려는 핵심. 가장 큰 공간을 차지해야 함.
|
||||
- **배경**: 본심을 이해하기 위한 도입/배경. 간결하게.
|
||||
- **첨부**: 본심을 보조하는 참조 정보 (용어 정의 등). sidebar 배치.
|
||||
- **결론**: 절대 잊으면 안 되는 핵심 한 줄. footer.
|
||||
|
||||
각 역할에 해당하는 topic_ids와 공간 비중(weight, 합계 1.0)을 결정하라.
|
||||
콘텐츠에 따라 비중은 매번 달라진다. 고정값이 아니다.
|
||||
```
|
||||
|
||||
**충돌:** 없음. 기존 출력 필드에 page_structure 추가만. `.get()` 방식이라 무시 가능.
|
||||
|
||||
#### M-1b: pipeline.py에서 Kei weight 읽기
|
||||
|
||||
**위치:** `src/pipeline.py` Phase L 공간 할당 부분 (현재 132~165행)
|
||||
|
||||
**변경:** PURPOSE_WEIGHT 대신 Kei 출력 weight 사용
|
||||
```python
|
||||
# 현재 (Phase L 하드코딩):
|
||||
allocation = allocate_height_budget(zone_blocks, zone_info.get("budget_px", 490))
|
||||
|
||||
# 변경 (Phase M Kei 판단):
|
||||
page_struct = analysis.get("page_structure", {})
|
||||
weight_map = {}
|
||||
for role_name, role_info in page_struct.items():
|
||||
for tid in role_info.get("topic_ids", []):
|
||||
weight_map[tid] = role_info.get("weight", 0.25)
|
||||
allocation = allocate_height_budget(
|
||||
zone_blocks, zone_info.get("budget_px", 490),
|
||||
weight_override=weight_map
|
||||
)
|
||||
```
|
||||
|
||||
#### M-1c: allocate_height_budget() 시그니처 변경
|
||||
|
||||
**위치:** `src/space_allocator.py` (42~75행)
|
||||
|
||||
**변경:** `weight_override` 파라미터 추가
|
||||
```python
|
||||
def allocate_height_budget(
|
||||
blocks, zone_budget_px, gap_px=20,
|
||||
weight_override=None, # {topic_id: weight} — Kei 판단 기반
|
||||
):
|
||||
# weight_override 있으면 사용, 없으면 PURPOSE_WEIGHT fallback
|
||||
for block in blocks:
|
||||
tid = block.get("topic_id")
|
||||
if weight_override and tid in weight_override:
|
||||
weight = weight_override[tid]
|
||||
else:
|
||||
purpose = block.get("purpose", "")
|
||||
weight = PURPOSE_WEIGHT.get(purpose, 0.25)
|
||||
weights.append(weight)
|
||||
```
|
||||
|
||||
**PURPOSE_WEIGHT:** fallback으로 유지 (Kei가 page_structure 안 줬을 때). 하드코딩 → fallback 강등.
|
||||
|
||||
#### M-1d: STEP_B_PROMPT에 weight 전달
|
||||
|
||||
**위치:** `src/design_director.py` STEP_B_PROMPT user_prompt 구성부
|
||||
|
||||
**추가:** Kei가 판단한 비중을 팀장에게 전달
|
||||
```
|
||||
## 페이지 구조 (Kei 실장 판단)
|
||||
- 본심 (꼭지 2, 3): 공간 비중 60% — body에서 가장 크게
|
||||
- 배경 (꼭지 1): 공간 비중 15% — compact 도입부
|
||||
- 첨부 (꼭지 4): 공간 비중 15% — sidebar 참조
|
||||
- 결론 (꼭지 5): 공간 비중 10% — footer 한 줄
|
||||
|
||||
본심에 가장 큰 블록을, 배경에 가장 작은 블록을 배정하라.
|
||||
비중을 무시하고 동등하게 배치하지 마라.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### M-Step 2: 역할-블록 매핑
|
||||
|
||||
#### M-2a: FAISS 쿼리 강화
|
||||
|
||||
**위치:** `src/block_search.py` `_build_query()` (178~188행)
|
||||
|
||||
**변경:** purpose + relation_type + expression_hint 추가
|
||||
```python
|
||||
def _build_query(topic):
|
||||
parts = [
|
||||
topic.get("title", ""),
|
||||
topic.get("summary", ""),
|
||||
f"역할: {topic.get('role', 'flow')}",
|
||||
f"레이어: {topic.get('layer', 'core')}",
|
||||
f"목적: {topic.get('purpose', '')}", # 추가
|
||||
f"관계: {topic.get('relation_type', '')}", # 추가
|
||||
f"표현: {topic.get('expression_hint', '')}", # 추가
|
||||
]
|
||||
if topic.get("content_type"):
|
||||
parts.append(f"콘텐츠: {topic['content_type']}")
|
||||
return ". ".join(p for p in parts if p)
|
||||
```
|
||||
|
||||
#### M-2b: STEP_B_PROMPT 역할×성격 매트릭스
|
||||
|
||||
**위치:** `src/design_director.py` purpose 가이드 섹션
|
||||
|
||||
**기존 Phase K 규칙 유지 + 아래 매트릭스 추가:**
|
||||
```
|
||||
## 역할 × 콘텐츠 성격 블록 매트릭스
|
||||
|
||||
| 역할 | 비교(comparison) | 구조(hierarchy/inclusion) | 정의(definition) | 흐름(sequence) |
|
||||
|------|-----------------|------------------------|-----------------|---------------|
|
||||
| 본심 | compare-2col-split, compare-3col-badge | keyword-circle-row, venn-diagram | card-numbered(large) | process-horizontal, flow-arrow-horizontal |
|
||||
| 배경 | topic-left-right(compact) | topic-left-right(compact) | quote-question(compact) | topic-left-right(compact) |
|
||||
| 첨부 | card-numbered(sidebar) | card-numbered(sidebar) | card-numbered(sidebar), dark-bullet-list(sidebar) | card-numbered(sidebar) |
|
||||
| 결론 | banner-gradient | banner-gradient | banner-gradient | banner-gradient |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### M-Step 3: 블록 안전성
|
||||
|
||||
#### M-3a: catalog.yaml figma_source 필드 (P-5)
|
||||
|
||||
**추가할 필드:** 각 블록에 `figma_source: true/false`
|
||||
|
||||
#### M-3b: zone 적합성 검증 (P-6)
|
||||
|
||||
**위치:** `src/design_director.py` `_validate_height_budget()` 내
|
||||
|
||||
**추가:** sidebar에 FULL_WIDTH_ONLY_BLOCKS 배치 시 교체/경고
|
||||
|
||||
#### M-3c: 글자 수용량 (P-7)
|
||||
|
||||
**위치:** `templates/catalog.yaml`
|
||||
|
||||
**추가:** 각 블록에 zone별 max_chars
|
||||
```yaml
|
||||
- id: compare-2col-split
|
||||
max_chars:
|
||||
body: {left: 200, right: 200, criteria: 30} # 65% 너비 기준
|
||||
sidebar: null # sidebar 사용 불가
|
||||
```
|
||||
|
||||
#### M-3d: 내부 overflow 감지 (P-8)
|
||||
|
||||
**위치:** `src/slide_measurer.py` _MEASURE_SCRIPT
|
||||
|
||||
**확인:** 현재 JS가 블록 내부 `scrollHeight > clientHeight + 2` 이미 체크 중.
|
||||
`overflow: auto` 블록(compare-3col-badge)의 수평 스크롤도 `scrollWidth > clientWidth` 체크 추가.
|
||||
|
||||
---
|
||||
|
||||
### M-Step 4: 원본 보존
|
||||
|
||||
#### M-4a: 토픽별 source_text 추출
|
||||
|
||||
**위치:** `src/pipeline.py` Stage 3 호출 전
|
||||
|
||||
**추가:** Kei가 출력한 source_hint + source_data를 기반으로 원본에서 텍스트 추출
|
||||
```python
|
||||
# 토픽별 원본 텍스트 매핑 구성
|
||||
topic_sources = {}
|
||||
for topic in analysis.get("topics", []):
|
||||
source_hint = topic.get("source_hint", "")
|
||||
source_data = topic.get("source_data", "")
|
||||
topic_sources[topic["id"]] = {
|
||||
"hint": source_hint,
|
||||
"data": source_data,
|
||||
}
|
||||
```
|
||||
|
||||
#### M-4b: fill_content() 프롬프트에 토픽별 source 전달
|
||||
|
||||
**위치:** `src/content_editor.py` fill_content() user_prompt 구성부
|
||||
|
||||
**추가:**
|
||||
```
|
||||
## 토픽별 원본 데이터 (이 텍스트에서 추출하라. 재작성 금지.)
|
||||
- 토픽 1: [source_hint 내용]
|
||||
- 토픽 2: [source_hint 내용]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 충돌/회귀/하드코딩 최종 검증
|
||||
|
||||
| Step | 충돌 | 회귀 | 하드코딩 | Kei/Sonnet |
|
||||
|------|:---:|:---:|:------:|:----------:|
|
||||
| M-1a KEI_PROMPT | 없음 | 없음 | **Kei 판단** | Kei |
|
||||
| M-1b pipeline weight | 없음 | Phase L 개선 | **Kei weight** | — |
|
||||
| M-1c allocate 시그니처 | 없음 | 없음 | fallback만 | — |
|
||||
| M-1d STEP_B weight | 없음 | 없음 | **Kei → 팀장** | Sonnet(기존) |
|
||||
| M-2a FAISS 쿼리 | 없음 | 없음 | 없음 | — |
|
||||
| M-2b 매트릭스 | Phase K 위에 확장 | 없음 | 없음 | Sonnet(기존) |
|
||||
| M-3a Figma | 없음 (신규) | 없음 | 없음 | — |
|
||||
| M-3b zone맵 | Phase J 보강 | 없음 | 상수(범용) | — |
|
||||
| M-3c max_chars | Phase I 보강 | 없음 | 없음 | — |
|
||||
| M-3d 내부overflow | Phase L 확장 | 없음 | 없음 | — |
|
||||
| M-4a source 추출 | 없음 (신규) | 없음 | 없음 | — |
|
||||
| M-4b 편집자 강화 | Phase J 보강 | 없음 | 없음 | Kei(편집자) |
|
||||
|
||||
---
|
||||
|
||||
## 이력
|
||||
|
||||
| 날짜 | 내용 |
|
||||
|------|------|
|
||||
| 2026-03-26 | Phase I~L 전체 실행 후 결과물 분석. 외부 진단(P-1~P-9) 수용. 비중 시스템(Kei 판단, 하드코딩 아님) 기반 전면 재설계. Phase M 계획 수립. |
|
||||
| 2026-03-26 | 기술 조사 + 충돌/회귀 정밀 검토 완료. M-Step 1~4 실행 방안 상세 확정. |
|
||||
Reference in New Issue
Block a user