Files
C.E.L_Slide_test2/docs/history/PHASE-W-PLAN.md
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

12 KiB
Raw Blame History

Phase W — 실행 계획 (Task별 방향 + 방법)

작성일: 2026-04-03 상위 문서: PHASE-W.md


W-1: space_allocator — weight 비율 초기 배정

W-1-1: zone_budget을 weight 비율로 계산

현재: zone_budget = zone_info.get("budget_px") → 프리셋 490px 고정 방향: zone_budget = total_available × zone_weight_sum / all_weight_sum 파일: src/space_allocator.pycalculate_container_specs() 내부 방법:

  • 전체 가용 높이 = slide_height - padding×2 - gap×2 - header
  • 각 zone의 weight 합을 구함 (body zone = 배경+본심 weight, sidebar = 첨부 weight 등)
  • 전체 weight 합 대비 비율로 zone_budget 계산
  • 이전에 구현했던 코드를 다시 적용 (173113 run에서 동작 확인됨) 검증: weight 합 1.0일 때 모든 컨테이너 높이 합 출력하여 전체 가용의 95% 이상인지 확인

W-1-2: 전체 공간 100% 사용

방향: W-1-1이 해결되면 자동으로 해결 검증: stage_1_5a_context.json에서 모든 컨테이너 height_px 합산 ≥ 전체 가용 × 0.95

W-1-3: 시선 흐름 배치 좌표

현재: _calc_coords()가 배경→상단좌, 본심→중앙좌, 첨부→우측, 결론→하단으로 배치 방향: 현재 코드 유지 (이미 올바름) 검증: stage_1_8_filled.html에서 배경이 상단, 본심이 중앙, 첨부가 우측, 결론이 하단에 위치


W-2: block_assembler — 공통 조립 함수 완성

W-2-1: font_hierarchy override

현재: _override_font() 함수가 블록 CSS의 font-size를 font_hierarchy로 조정 방향: 현재 코드 유지 검증: filled HTML에서 첨부 영역의 font-size가 sidebar 값(9-11px)을 초과하지 않음

W-2-2: 팝업 링크 인접 배치

현재: _parse_structured_text()에서 [팝업: 제목]을 이전 불릿 텍스트에 [제목→]으로 붙임 방향: 현재 코드 유지 검증: filled HTML에서 [혼용 대표 사례→]가 별도 줄이 아니라 텍스트 옆에 붙어있음

W-2-3: sidebar 상단 라벨

현재: _assemble_card_numbered()에서 topic.title을 라벨로 추가 방향: 현재 코드 유지 검증: filled HTML의 첨부 영역 상단에 꼭지 title이 보임

W-2-4: 카드 indent 파싱

현재: _assemble_card_numbered()에서 indent=0만 카드 제목, indent=1은 설명 방향: 현재 코드 유지 검증: 첨부에 건설산업/BIM/DX 3개 카드가 분리되고, 하위 설명이 각 카드 안에 있음

W-2-5: 카드 불릿 간격

현재: CSS override에서 white-space: pre-line → normal 변환 방향: 현재 코드 유지 검증: 첨부 카드 내 불릿과 불릿 사이에 빈 줄(엔터)이 없음

W-2-6: 실제 이미지 사용

현재: has_real_image 분기로 실제 이미지 있으면 SVG 레이아웃, 없으면 텍스트만 방향: 수정 필요 — 현재 _assemble_svg_layout()design_reference_html에서 SVG를 추출. 이걸 ctx.slide_images의 실제 이미지(base64)로 교체 파일: src/block_assembler.py_assemble_svg_layout() 방법:

  • ctx.slide_images에서 해당 이미지의 base64 데이터를 가져옴
  • <img src="data:image/png;base64,{b64}" /> 형태로 삽입
  • SVG viewBox/gradient 하드코딩 대신 실제 이미지 사용 검증: filled HTML에 <img src="data:image/png;base64, 패턴이 있고, SVG 태그가 없음

W-2-7: filled/assembled 통일

현재: _gen_stage_1_8_filled()assemble_slide_html() 호출 방향: assembled(stage_2_code_assembled)도 같은 함수 호출하도록 assemble_stage2.py 수정 또는 제거 검증: filled와 assembled가 같은 HTML 구조를 가짐 (diff로 확인)

W-2-8: 팝업 마크다운 테이블 변환

현재: mdx_normalizer.py_extract_popup()에서 _convert_md_table_to_html() 호출 방향: 현재 코드 유지 검증: stage_0_context.json의 popups에서 "DX와 BIM의 구분" 팝업에 <table> 태그가 있고 | 마크다운이 없음


W-3: filled → Selenium 측정 연결

W-3-1: .slide 클래스

현재: assemble_slide_html()의 최외곽 div에 class="slide" 있음 방향: 현재 코드 유지 검증: filled HTML에서 class="slide" 존재 확인

W-3-2: area-* 클래스

현재: 각 역할 컨테이너에 area-body, area-sidebar, area-footer 클래스 있음 방향: 현재 코드 유지 검증: filled HTML에서 area-body, area-sidebar, area-footer 존재 확인

W-3-3: Selenium 측정 정상 동작

현재: 173113 run에서 {'error': 'slide not found'} 발생 (당시 .slide 클래스 없었음) 방향: W-3-1, W-3-2가 해결되면 자동 해결 방법: filled HTML을 measure_rendered_heights()에 넣고 정상 결과 반환 확인 검증: 반환값에 zones.sidebar.scrollHeight, zones.body.scrollHeight 등이 있고 error 키가 없음

W-3-4: 시각화 순서 (before → filled → after)

현재: step_visualizer.py의 dispatch에서 blocks → filled → fit_before → fit_after 순서 방향: before(빈 컨테이너 크기) → filled(블록+텍스트 채운 상태) → after(조정된 크기) 순서 파일: src/step_visualizer.pygenerate_step_html() 방법:

  • stage_1_8 dispatch 순서를 fit_before → filled → fit_after로 변경
  • fit_before는 빈 컨테이너 크기만 보여줌 (부족/여유 판단 없이)
  • filled는 블록+텍스트 채운 상태
  • fit_after는 조정 후 컨테이너 크기 검증: steps 폴더에 3개 파일이 순서대로 있고, before의 크기 → filled의 넘침 → after의 변경이 시각적으로 확인 가능

W-4: 측정 결과 기반 조정 판단

W-4-1: sidebar overflow → 확장

현재: pipeline.py Stage 1.8에 sidebar 확장 코드 있음 방향: 현재 코드 유지 (Selenium 측정이 동작하면 자동으로 발동) 검증: sidebar scrollHeight > clientHeight일 때 stage_1_8_context.json의 첨부 height_px가 scrollHeight 이상으로 증가

W-4-2: body overflow → 재배분

현재: redistribute() 함수가 body zone 내에서 배경↔본심 재배분 방향: 현재 코드 유지 검증: body overflow 시 배경 또는 본심의 height_px가 변경됨

W-4-3: 재배분 후에도 overflow → Kei 에스컬레이션

현재: needs_escalation=True일 때 call_kei_fit_escalation() 호출 방향: 현재 코드 유지 검증: enhancement_result.kei_decisions에 Kei 응답이 저장됨

W-4-4: Kei trim/popup 결정 실제 적용

현재: Kei 결정을 받지만 실제 반영 안 됨 방향: 새로 구현 파일: src/pipeline.py Stage 1.8 내부 + 새 함수

trim 구현 방법:

  • Kei가 {"action": "trim", "detail": "150자로 축약"}을 반환하면
  • 해당 role의 topic structured_text를 Kei/Sonnet에게 축약 요청 (AI 판단 — 어떤 문장이 덜 중요한지는 AI만 알 수 있음)
  • 프롬프트: "다음 텍스트를 N자 이내로 축약하라. 불릿 구조 유지. 핵심 85% 보존."
  • 축약된 텍스트로 structured_text 교체
  • 하드코딩 없음 — 어떤 콘텐츠든 AI가 판단
  • 도구: anthropic SDK (이미 있음), Kei API /api/direct

popup 구현 방법:

  • Kei가 {"action": "popup", "detail": "상세 정의를 팝업으로"}를 반환하면
  • 해당 role의 structured_text를 Kei/Sonnet에게 분리 요청 ("요약 vs 상세" 판단)
  • 프롬프트: "다음 콘텐츠를 슬라이드 요약(2-3줄)과 팝업 상세로 분리하라."
  • 요약은 structured_text에, 상세는 별도 팝업 HTML로 저장
  • 슬라이드에는 요약 + [상세보기→] 링크
  • 하드코딩 없음 — 어떤 콘텐츠든 AI가 요약/상세를 판단
  • 도구: anthropic SDK, 팝업 HTML 템플릿 (pipeline.py Stage 5에 이미 있음)

검증: trim 후 structured_text 길이가 줄어들고, popup 후 팝업 HTML 파일이 생성됨

W-4-5: Kei restructure → 컨테이너 직접 변경

현재: redistribute() 재실행만 됨 방향: Kei가 "본심에 363px 보장"하면 직접 height_px 변경 파일: src/pipeline.py Stage 1.8 내부 방법:

  • Kei 결정에서 구체적 px 값을 파싱 (정규식으로 숫자 추출)
  • 해당 role의 height_px를 직접 설정
  • 다른 role에서 부족분을 weight 역비례로 차감 (중요도 낮은 곳에서 더 많이)
  • 최소 높이(60px) 보장
  • 총합이 전체 가용 초과하지 않도록 검증
  • 하드코딩 없음 — 순수 산술, 어떤 role이든 동작
  • 도구: Python 산술 (외부 라이브러리 불필요)

검증: restructure 후 해당 role의 height_px가 Kei가 지정한 값으로 변경되고, 총합이 전체 가용 이하

W-4-6: after 컨테이너 저장

현재: stage_1_8_context.json에 containers 저장됨 방향: 현재 코드 유지 (W-4-1~5의 결과가 containers에 반영되면 자동 저장) 검증: stage_1_8_context.json의 containers가 before와 다름

W-4-7: Kei 보강 검토 호출

현재: call_kei_enhancement_review() 함수 있고 pipeline.py에서 호출 방향: 현재 코드 유지 검증: enhancement_result에 Kei 보강 검토 결과가 저장됨 (approve/modify/reject)


W-5: after 기반 최종 조립 + 검증

W-5-1: stage_2가 after 컨테이너 사용

현재: stage_2_context.json의 containers == stage_1_8_context.json의 containers (확인됨) 방향: 현재 코드 유지 검증: 두 JSON의 containers 비교 — 일치

W-5-2: overflow 없음 확인

현재: Stage 4에서 Selenium 측정. Vision 모델 ID 404 에러 방향: Vision 모델 ID를 claude-sonnet-4-20250514로 변경 (vision 지원, 비용 효율) 파일: src/kei_client.py — 3곳 방법: 모델 ID 문자열 교체 검증: Stage 4에서 모든 zone의 excess_px ≤ 0

W-5-3: 텍스트 85% 보존 검증

현재: 검증 로직 없음 방향: 새로 구현 파일: src/pipeline.py Stage 4 또는 Stage 5 방법:

  • final.html에서 HTML 태그 제거하여 순수 텍스트 추출 (Python stdlib html.parser)
  • 각 role의 structured_text와 문자 3-gram 겹침 비교
  • 85% 이상이면 PASS
  • 하드코딩 없음 — 문자열 비교만, 어떤 콘텐츠든 동작
  • 도구: Python stdlib만 (html.parser, re). 외부 NLP 불필요

검증: 검증 함수가 각 role별 보존율을 반환하고, 모든 role이 85% 이상


의존 관계

W-1-1 → W-1-2 (자동)
W-1 + W-2 → W-3 (filled 생성 + 측정)
W-3 → W-4 (측정 결과로 판단)
W-4 → W-5 (after 기반 최종)

W-2 내부: 1~8 독립적으로 병행 가능
W-4 내부: 1→2→3→4/5 순차, 6/7 독립

필요 도구/라이브러리

도구 용도 상태
Selenium + Chrome headless filled 측정 (W-3) 설치됨, 동작 확인
anthropic SDK Kei trim/popup (W-4-4), Vision (W-5-2) 설치됨
httpx Kei API 호출 설치됨
Kei API (localhost:8000) 에스컬레이션, 보강 검토 동작 확인
Python stdlib (html.parser, re) 텍스트 보존 검증 (W-5-3) 내장
Jinja2 블록 템플릿 렌더링 설치됨

추가 설치 필요 없음.


실행 순서

Phase 1: W-1 (weight 비율) — 기반
Phase 2: W-2 (공통 조립 함수) — W-1과 병행 가능
Phase 3: W-3 (Selenium 연결) — W-1 + W-2 필요
Phase 4: W-4 (판단 로직) — W-3 필요
Phase 5: W-5 (최종 검증) — W-4 필요

각 Phase 완료 후 파이프라인 실행하여 검증.