Phase H 보완 구현: 1단계 A/B 분리 + 정밀 검토 8개 반영
H-1a: KEI_PROMPT에 제목 중복 방지 지시 추가 H-1b: KEI_PROMPT_B (컨셉 구체화) + refine_concepts() 신규 함수 - 각 꼭지의 relation_type, expression_hint, source_data 판단 - 1회 호출로 전체 꼭지 처리 - session_id: "design-agent-refine" (별도) - 실패 시 1단계-A 결과 그대로 반환 (pipeline 안 멈춤) H-5: 팀장에게 relation_type + expression_hint + source_data 전달 - 꼭지 요약에 관계/표현/원본데이터 포함 section-title-with-bg body 금지: - STEP_B_PROMPT에 규칙 추가 - BODY_FORBIDDEN_MAP + _validate_height_budget에서 코드 레벨 교체 manual_classify fallback 동기화: - core_message, purpose, source_hint 기본값 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -258,6 +258,8 @@ header/footer는 고정이므로 건드리지 않는다.
|
||||
- 너비 35% 이하 zone(sidebar)에는 카드 1열, 시각화 블록 금지
|
||||
- catalog의 when/not_for와 height_cost를 반드시 읽고 선택
|
||||
- 같은 블록 타입 반복 금지 — 다양한 블록 활용
|
||||
- **section-title-with-bg는 body/sidebar/footer zone에서 사용 금지.** 이 블록은 자세히보기 전용 페이지 상단에만 사용.
|
||||
- 각 꼭지의 relation_type과 expression_hint를 보고 적합한 블록을 선택하라
|
||||
|
||||
## purpose 기반 블록 선택 가이드 (참고, 강제 아님)
|
||||
각 꼭지의 purpose에 맞는 블록 계열을 선택하라:
|
||||
@@ -472,7 +474,10 @@ async def create_layout_concept(
|
||||
line = (
|
||||
f"꼭지 {t.get('id', '?')}: {t.get('title', '?')} "
|
||||
f"[{t.get('layer', '?')}, ROLE:{role}, "
|
||||
f"강조:{t.get('emphasis', False)}]"
|
||||
f"강조:{t.get('emphasis', False)}, "
|
||||
f"관계:{t.get('relation_type', '?')}, "
|
||||
f"표현:{t.get('expression_hint', '?')}, "
|
||||
f"원본데이터:{t.get('source_data', '?')}]"
|
||||
)
|
||||
if t.get("detail_target"):
|
||||
line += " → ★detail_target (callout-solution으로 요약 배치 권장)"
|
||||
@@ -665,6 +670,11 @@ HEIGHT_COST_PX = {
|
||||
"xlarge": 400,
|
||||
}
|
||||
|
||||
# body/sidebar/footer zone에서 사용 금지인 블록 → 교체
|
||||
BODY_FORBIDDEN_MAP = {
|
||||
"section-title-with-bg": "topic-center", # 500px 블록 → compact 헤더로
|
||||
}
|
||||
|
||||
# xlarge/large → medium/compact 교체 후보
|
||||
DOWNGRADE_MAP = {
|
||||
"venn-diagram": "card-icon-desc",
|
||||
@@ -701,6 +711,7 @@ def _load_catalog_map_for_height() -> dict[str, str]:
|
||||
def _validate_height_budget(blocks: list[dict], preset: dict) -> None:
|
||||
"""zone별 height_cost 합산을 검증하고, 초과 시 큰 블록을 교체한다.
|
||||
|
||||
또한 body/sidebar/footer zone에서 금지된 블록을 교체한다.
|
||||
코드 레벨 검증 — Sonnet이 높이 예산을 안 지켜도 강제 교정.
|
||||
"""
|
||||
zones = preset.get("zones", {})
|
||||
@@ -714,6 +725,17 @@ def _validate_height_budget(blocks: list[dict], preset: dict) -> None:
|
||||
zone_blocks[area] = []
|
||||
zone_blocks[area].append(block)
|
||||
|
||||
# 금지 블록 교체 (body/sidebar/footer에서 사용 불가한 블록)
|
||||
for block in blocks:
|
||||
area = block.get("area", "body")
|
||||
block_type = block.get("type", "")
|
||||
if area != "header" and block_type in BODY_FORBIDDEN_MAP:
|
||||
replacement = BODY_FORBIDDEN_MAP[block_type]
|
||||
logger.warning(
|
||||
f"[금지 블록 교체] {block_type} → {replacement} (area={area})"
|
||||
)
|
||||
block["type"] = replacement
|
||||
|
||||
for area, area_blocks in zone_blocks.items():
|
||||
zone_info = zones.get(area, {})
|
||||
budget = zone_info.get("budget_px", 490)
|
||||
|
||||
Reference in New Issue
Block a user