XBX-2 완료: overflow 프로세스 정상 동작

- slide_measurer: data URI → 임시파일 방식 (대용량 HTML 측정 가능)
- pipeline: Type B zone 간 재배분 (top↔bottom 공간 이전)
- pipeline: overflow 분기에 top/bottom zone 추가
- kei_client: 에스컬레이션 prompt 개선
  - 텍스트 원문 보존 원칙 명시 (삭제/요약/압축 금지)
  - action을 popup만으로 제한
  - 실제 역할명 목록을 prompt에 전달
- block_assembler: Kei popup 결정 반영 (해당 역할 콘텐츠 → 팝업 링크)

결과: 02번 상단 카드 3개 모두 표시, 하단 우측 표 → 팝업 분리

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 07:39:02 +09:00
parent 028f611070
commit 095abdf9af
4 changed files with 95 additions and 39 deletions

View File

@@ -552,6 +552,10 @@ async def generate_slide(
# body: 배경↔본심 재배분으로 처리 (후속 redistribute에서)
logger.info(f"[Stage 1.8] body overflow +{excess}px — 재배분 필요")
elif zone_name in ("top", "bottom"):
# Type B: top/bottom overflow → 후속 에스컬레이션에서 Kei 요약 요청
logger.info(f"[Stage 1.8] {zone_name} overflow +{excess}px — 콘텐츠 축소 필요")
# containers_dict 업데이트 (sidebar 확장 반영)
for role, ci in updated_containers.items():
containers_dict[role] = {
@@ -572,6 +576,26 @@ async def generate_slide(
)
fit_analysis = redistribute(fit_analysis, containers_dict)
# Type B: zone 간 재배분 (top↔bottom)
# redistribute는 같은 zone 내에서만 동작하므로, Type B는 zone 간 여유를 수동 이전
if context.analysis.layout_template == "B":
deficit_roles = [(r, rf.shortfall_px) for r, rf in fit_analysis.roles.items() if rf.shortfall_px > 0]
surplus_roles = [(r, abs(rf.shortfall_px)) for r, rf in fit_analysis.roles.items() if rf.shortfall_px < -8]
if deficit_roles and surplus_roles:
total_deficit = sum(d for _, d in deficit_roles)
total_surplus = sum(s for _, s in surplus_roles)
transferable = min(total_deficit, total_surplus)
if transferable > 0:
for role, deficit in deficit_roles:
share = transferable * (deficit / total_deficit)
old = fit_analysis.redistribution.get(role, fit_analysis.roles[role].allocated_px)
fit_analysis.redistribution[role] = old + share
for role, surplus in surplus_roles:
share = transferable * (surplus / total_surplus)
old = fit_analysis.redistribution.get(role, fit_analysis.roles[role].allocated_px)
fit_analysis.redistribution[role] = old - share
logger.info(f"[Stage 1.8] Type B zone 간 재배분: {transferable:.0f}px 이전")
# ── after: 조정된 컨테이너 ──
for role, ci in updated_containers.items():
new_h = fit_analysis.redistribution.get(role, ci.height_px) if fit_analysis.redistribution else ci.height_px
@@ -590,6 +614,7 @@ async def generate_slide(
fit_report=report,
topics=[t.model_dump() for t in context.topics],
content_summary=context.raw_content[:1500],
role_names=list(context.page_structure.roles.keys()),
)
kei_decisions = []
if kei_result: