Files
kyeongmin c42e01f060 문서 정리: 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>
2026-04-13 10:56:23 +09:00

163 lines
7.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 `<table>`로 변환되어 `stage_0_context.json`의 popups에 저장됨 |
---
## W-3: filled → Selenium 측정 연결
> 파일: `src/block_assembler.py`, `src/pipeline.py`
| Task | 완료 기준 |
|------|-----------|
| W-3-1 | `assemble_slide_html()` 출력 HTML에 `.slide` 클래스가 최외곽 div에 있음 |
| W-3-2 | 각 역할 컨테이너에 `.area-body`, `.area-sidebar`, `.area-footer` 클래스가 있음 |
| W-3-3 | filled HTML을 `measure_rendered_heights()`에 넣으면 `{'error': 'slide not found'}`가 아닌 정상 측정 결과가 반환됨 |
| W-3-4 | steps 폴더에 `stage_1_8_fit_before.html``stage_1_8_filled.html``stage_1_8_fit_after.html` 순서로 생성되고, before의 컨테이너 크기 → filled의 넘침 → after의 조정된 크기가 시각적으로 확인 가능 |
---
## W-4: 측정 결과 기반 조정 판단
> 파일: `src/pipeline.py`, `src/fit_verifier.py`, `src/kei_client.py`
| Task | 완료 기준 |
|------|-----------|
| W-4-1 | pipeline.py Stage 1.8에서 filled 측정 후 sidebar overflow 감지 시 해당 role의 컨테이너 height_px가 scrollHeight로 확장됨 |
| W-4-2 | body overflow 감지 시 `redistribute()`가 호출되어 배경↔본심 간 높이가 재배분됨 |
| W-4-3 | 재배분 후에도 overflow이면 `call_kei_fit_escalation()`이 호출됨 |
| W-4-4 | Kei가 trim 결정 시 해당 role의 structured_text가 축약되거나, popup 결정 시 해당 콘텐츠가 팝업으로 분리됨 |
| W-4-5 | Kei가 restructure 결정 시 해당 role의 컨테이너 height_px가 변경됨 |
| W-4-6 | after의 컨테이너 크기가 stage_1_8_context.json에 저장됨 |
| W-4-7 | Stage 1.8에서 `call_kei_enhancement_review()`가 호출되고, Kei 응답이 `enhancement_result`에 저장됨 |
---
## W-5: after 기반 최종 조립 + 검증
> 파일: `src/pipeline.py`, `src/block_assembler.py`
| Task | 완료 기준 |
|------|-----------|
| W-5-1 | stage_2의 `generated_html`이 after 컨테이너 크기를 기준으로 생성됨 (stage_2_context.json의 containers == stage_1_8_context.json의 containers) |
| W-5-2 | stage_3_rendered.html에서 overflow가 없음 (Stage 4 측정에서 모든 zone excess ≤ 0) |
| W-5-3 | final.html에 모든 역할의 structured_text가 85% 이상 포함됨 |
---
## 의존 관계
```
W-1 (weight 초기 배정)
W-2 (공통 조립 함수) ← 독립적으로 병행 가능
W-3 (filled → Selenium 측정) ← W-1 + W-2 필요
W-4 (측정 기반 판단) ← W-3 필요
W-5 (after 기반 최종) ← W-4 필요
```
---
## 미결정 사항
- **Sonnet vs 코드 조립**: Stage 2를 Sonnet으로 유지할지 block_assembler 코드 조립으로 교체할지는 W-1~W-5 완성 후 결과를 보고 판단.
---
## 입력 데이터
- MDX 파일: `samples/mdx/01. 건설산업 DX의 올바른 이해(0127).mdx`
- 이미지: `samples/images/` (DX1.png 등)
- 테스트: `scripts/run_from_stage1b.py` — Stage 1B 데이터 고정 실행
- 좋았던 Kei 데이터: `data/runs/20260403_133746` (또는 `20260403_163508`)