# Phase Y: slide-base 기반 블록 조립 파이프라인 재설계 > **작성일:** 2026-04-14 > **목적:** assembler를 slide-base.html 기반으로 재작성. 블록 선택 → 배치 → 측정 → 조정 루프 완성. > **근거:** Phase X-BX까지 assembler가 slide-base를 무시하고 HTML을 처음부터 생성. 블록 선택(1.7)이 조립(Stage 2)에 반영 안 됨. Stage 4 품질 점수 거짓말. 전체 파이프라인 연결 끊김. --- ## 핵심 전환 ``` [이전] assembler가 HTML 전체를 하드코딩 생성. 블록 무시. slide-base 미사용. [이후] slide-base.html 위에 tag 매칭된 블록을 배치. 사전계산 + 실측 조정 루프. ``` --- ## 전체 흐름 (2026-04-15 재설계) ``` [1] slide-base.html 로드 ├── title → .slide-title ├── 핵심요약(:::note) → .slide-footer (footer_text) └── .slide-body (590px 가용) → 영역(zone)들이 여기에 배치됨 [2] Stage 1A: Kei 꼭지 추출 (영역 없이, 꼭지만) ├── Kei에게 zone/영역 판단을 시키지 않음 ├── 꼭지별 title, purpose, layer, relation_type만 추출 └── 핵심요약은 conclusion_text로 분리 [3] 코드: MDX ## 파싱 → 꼭지-대목차 매핑 ├── MDX에서 ## 대목차 목록 추출 (## 없는 도입부도 포함) ├── 각 꼭지의 source_data/title이 어느 ## 아래에 속하는지 매핑 └── 대목차별 꼭지 묶음 생성 [4] 코드: 대목차별 묶음으로 블록 tag 매칭 시도 (영역 확정 단계) ├── 묶음별 item_count + 꼭지 title → catalog tag 검색 ├── 매칭됨 → 이 묶음 = 하나의 영역 (코드가 확정, 블록도 확정) └── 매칭 안 됨 → Kei에게 이 꼭지들의 영역 판단 요청 ├── "이 꼭지들을 어떻게 묶을지?" ├── "sidebar로 뺄 것이 있는지?" → Type A 결정 └── Kei는 주어진 꼭지 목록 안에서만 판단 (새 영역 이름 만들지 않음) [5] 영역 확정 + 콘텐츠 소스 결정 ├── 영역 제목 = MDX 원본 ## 제목 그대로 ├── 영역 콘텐츠 = normalized.sections에서 MDX 원본 텍스트 ├── Kei structured_text가 아님 (Kei는 구조 판단만) └── sidebar 지정된 영역 → Type A / 나머지 → Type B [6] 사전 계산: 영역별 비중 → 대략적 px 배정 └── 블록 후보 필터링 (너무 큰 블록 제외) [7] .slide-body에 블록 배치 + 실측 조정 루프 ├── 블록 템플릿 Jinja2 렌더링 (슬롯에 MDX 원본 텍스트 삽입) ├── slide-base + 블록 HTML 조합 ├── Selenium 측정 (measure_mode: overflow:auto) → overflow 확인 ├── overflow 시: │ ├── ① font/padding 조정 (CSS 변수, 코드) │ ├── ② 간격 축소 │ ├── ③ 텍스트 압축 (최후 수단, AI 1회) │ └── 재측정 (최대 3회 루프) └── overflow 없음 → 확정 [8] 최종 HTML 출력 └── slide-base + 확정된 블록들 = final.html (overflow:hidden) [9] 품질 검증 ├── Selenium overflow 측정 ├── 비전 모델 평가 (가능할 때만) └── 미평가 시 -1 (거짓말 안 함) ``` ### 핵심 변경 (이전 대비) | 항목 | 이전 (문제) | 이후 (재설계) | |------|-----------|-------------| | 영역/zone 결정 | Kei가 zone 구조를 만듦 → 매번 다름, 오인 | 코드가 ##파싱 + 블록매칭으로 먼저 확정. 안 되는 것만 Kei | | 콘텐츠 소스 | Kei structured_text (재구성) | MDX 원본 (normalized.sections) | | 영역 제목 | Kei가 축약 ("필수요건") | MDX 원본 ## 제목 그대로 | | Kei 역할 | 꼭지+영역+zone+텍스트 전부 | 꼭지 추출 + 성격 판단(sidebar/팝업)만 | | 블록 매칭 시점 | 영역 확정 후 | 영역 확정 전 (블록이 영역을 결정) | --- ## 태스크 목록 ### Y-1: Kei 프롬프트 — zone = 대목차 (완료) - [x] zone = `##` 대목차 단위, `###` 소목차 = zone 안 블록 - [x] 2단계 판단: 먼저 zone 잡고 → 용어정의 있으면 Type A - [x] 결론/핵심요약 = slide-base footer (별도 zone 아님) - [ ] Kei 프롬프트에서 결론 zone 제거 (page_structure에서 제외) ### Y-2: space_allocator — zone=bottom 지원 - [ ] `bottom` zone 전체폭 처리 추가 - [ ] Type A/B에 따라 .slide-body 내 레이아웃 분기 - [ ] 결론 zone 미생성 (slide-base footer로 처리) ### Y-3: block_reference — tag 매칭 강화 - [x] tag 기반 0순위 매칭 추가 - [x] item_count 범위("2-3") 처리 - [ ] content_pattern 가중치 추가 (item_count만으로 매칭 방지) - [ ] 결론 role 매칭 제외 (slide-base가 처리) ### Y-4: assembler 재작성 — slide-base 기반 - [ ] slide-base.html 로드 → Jinja2 렌더링 - [ ] title, footer_text(핵심요약) 삽입 - [ ] .slide-body에 zone별 블록 HTML 삽입 - [ ] render_block_for_role()로 블록 렌더링 - [ ] 블록 CSS를 slide-base