# Phase W — Stage 1.8 before→filled→after 파이프라인 완성 > 작성일: 2026-04-03 > 근거: Phase V 이후 코드 조립/연결 과정에서 발견된 문제 8건 > 선행: Phase V (적합성 검증 + Kei 에스컬레이션) --- ## 배경 Phase V에서 설계한 before→filled→after 프로세스가 실제로 동작하지 않음. 코드는 부분적으로 존재하지만 연결이 안 되어 있고, 각 단계가 따로 놀고 있음. ### 발견된 문제 8건 1. **before→filled→after 파이프라인 연결 안 됨** — filled Selenium 측정 실패, 판단 미동작 2. **space_allocator 불안정** — weight 비율로 전체 공간 100% 사용해야 하는데 안 됨 3. **공통 조립 함수 불완전** — filled/assembled/stage_2가 각각 다른 코드 사용 4. **Kei 에스컬레이션 결정 미반영** — trim/popup/restructure 결정이 컨테이너에 반영 안 됨 5. **본심 OVERFLOW 미해소** — 재배분이 충분하지 않음 6. **filled 시각화 품질** — font_hierarchy, 카드 간격, 팝업 링크 등 미반영 7. **이미지 SVG 샘플 사용** — 실제 이미지(samples/images/) 대신 하드코딩 샘플 8. **Sonnet/코드 조립 경로 분리** — 두 경로가 각각 존재. Phase W 완성 후 판단 --- ## 핵심 프로세스 ``` before: weight 비중대로 전체 가용 공간 100% 배정 (초기 컨테이너) ↓ filled: before 컨테이너에 블록+텍스트 채움 (block_assembler 공통 함수) ↓ 측정: Selenium으로 실제 넘침 확인 ↓ 판단: 1. 다른 블록으로 바꿀 수 있나? (font_hierarchy 유지) 2. sidebar 넘침 → 세로 확장 (예외) 3. body 넘침 → 배경↔본심 재배분 4. 그래도 안 되면 → Kei 에스컬레이션 (trim/popup/restructure) 5. Kei 결정을 컨테이너에 실제 반영 6. 텍스트 85% 보존 우선 ↓ after: 조정된 컨테이너 ↓ assembled = after 기준으로 block_assembler 공통 함수로 최종 조립 ``` --- ## 절대 원칙 1. **하드코딩 금지** — 어떤 MDX가 들어와도 동일하게 동작 2. **결과물 HTML 직접 수정 안 함** — 파이프라인 프로세스를 수정 3. **이미지는 실제 파일만** — samples/images/에서 가져옴. SVG 샘플 금지 4. **텍스트 85% 보존** — 공간 부족 시 컨테이너를 늘림. 그래도 안 되면 Kei가 팝업 분리 5. **weight = 초기 배정 비율 + 충돌 시 우선순위** — 최종 높이가 아님 6. **배치는 시선 흐름** — 좌→우, 상→하 (배경 상단좌, 본심 중앙좌, 첨부 우측, 결론 하단) 7. **font_hierarchy 준수** — 핵심 14px, 본심 12px, 배경 10-12px, 첨부 9-11px 8. **조립 로직은 한 곳** — block_assembler.py. filled/assembled/stage_2 모두 이 함수 사용 9. **임의로 코드 되돌리지 않음** — 이해 안 되면 물어보고, 제안하고, 허락받고 실행 --- ## W-1: space_allocator — weight 비율 초기 배정 > 파일: `src/space_allocator.py` | Task | 완료 기준 | |------|-----------| | W-1-1 | `calculate_container_specs()`에서 zone_budget을 `전체가용 × zone_weight_sum / all_weight_sum`으로 계산하는 코드가 있음 | | W-1-2 | weight 합 1.0일 때 모든 컨테이너 높이 합 ≥ 전체 가용 공간의 95% | | W-1-3 | 배경이 본심보다 위에, 첨부가 우측에, 결론이 하단에 배치되는 좌표 계산이 `_calc_coords()`에서 동작함 | --- ## W-2: block_assembler — 공통 조립 함수 완성 > 파일: `src/block_assembler.py` | Task | 완료 기준 | |------|-----------| | W-2-1 | `assemble_role_html()`이 블록 CSS의 font-size를 font_hierarchy 값으로 override한 HTML을 반환함 | | W-2-2 | 팝업 `[팝업: 제목]` 마커가 별도 줄이 아니라 이전 불릿 텍스트 옆에 `[제목→]` 형태로 붙어있음 | | W-2-3 | sidebar 역할일 때 상단에 꼭지 title 라벨이 있음 | | W-2-4 | card-numbered에서 주불릿(indent=0)만 카드 제목, 하위불릿(indent=1)은 카드 설명으로 분리됨 | | W-2-5 | 카드 내 불릿 사이에 빈 줄(엔터) 없음 — white-space: normal 적용 | | W-2-6 | 이미지는 `ctx.slide_images`의 실제 파일(base64)만 사용, design_reference_html의 SVG 샘플 미사용 | | W-2-7 | `_gen_stage_1_8_filled()`와 assembled가 모두 `assemble_slide_html()`을 호출함 | | W-2-8 | Stage 0에서 팝업 콘텐츠의 마크다운 테이블이 HTML `