Rebuild run-001 from clean source mdx

This commit is contained in:
2026-04-03 12:08:13 +09:00
parent adef735228
commit 74197864ca
43 changed files with 1107 additions and 2687 deletions

View File

@@ -89,11 +89,10 @@ def validate_outputs(generated: dict, measurement: dict) -> tuple[str, list[str]
failures.append("Verify-DesignStructure")
actions.append("핵심 관계를 설명하는 시각적 관계도 블록을 본문 중심 구조로 유지한다.")
narrative_markers = ["DX와 BIM의 혼용 문제", "DX의 정의와 위치", "BIM과 핵심기술의 관계", "DX와 BIM 비교 핵심 포인트"]
if sum(1 for marker in narrative_markers if marker in visible_text) < 3:
narrative_markers = ["\uc6a9\uc5b4\uc758 \ud63c\uc6a9", "\ud63c\uc6a9 \ub300\ud45c \uc0ac\ub840", "\uc6a9\uc5b4 \uc815\uc758", "\uc6a9\uc5b4\uac04 \uc0c1\ud638\uad00\uacc4", "DX\uc640 BIM\uc758 \uad6c\ubd84", "\ud575\uc2ec \uc694\uc57d"]
if sum(1 for marker in narrative_markers if marker in visible_text) < 4:
failures.append("Verify-DesignNarrative")
actions.append("원문 주요 소제목과 읽기 순서가 유지되도록 본문 서사를 재구성한다.")
actions.append("\uc6d0\ubb38 \uc8fc\uc694 \uc18c\uc81c\ubaa9(\uc6a9\uc5b4\uc758 \ud63c\uc6a9, \uc0ac\ub840, \uc815\uc758, \uc0c1\ud638\uad00\uacc4, \ube44\uad50, \uc694\uc57d)\uacfc \uc77d\uae30 \uc21c\uc11c\uac00 \uac00\uc2dc \ud14d\uc2a4\ud2b8\uc5d0 \uc720\uc9c0\ub418\ub3c4\ub85d \uc7ac\uad6c\uc131\ud55c\ub2e4.")
if failures:
return "revise", sorted(set(failures)), list(dict.fromkeys(actions))
return "pass", [], []
@@ -179,10 +178,10 @@ def summarize_markdown_lines(text: str, limit: int = 8) -> list[str]:
def build_step_comment(title: str, artifact_path: Path, lines: list[str], verdict: str = "pass") -> str:
bullet_text = "\n".join(f"- {line}" for line in lines) if lines else "- ??? ???."
bullet_text = "\n".join(f"- {line}" for line in lines) if lines else "- ??? ??? ????."
return f"""?? ??
- {title} ???? ???? ??? ???.
- ??? ??: `{artifact_path.as_posix()}`
- {title} ?? ???? ?? ???? ?? run ???? ????.
- ?? ??: `{artifact_path.as_posix()}`
?? ??
{bullet_text}
@@ -383,6 +382,7 @@ def main() -> None:
"--input", str(input_file),
"--stage1a", str(stage1a),
"--stage1b", str(stage1b),
"--base-path", str(repo_root),
"--output-dir", str(output_dir),
]
completed = subprocess.run(cmd, cwd=str(DESIGN_AGENT_ROOT), capture_output=True, text=True)
@@ -457,7 +457,7 @@ KPI / 판정 결과
if 'width:100%; height:28px' in final_html_text:
status = "revise"
failures = sorted(set(failures + ["Verify-RenderedSidebarBadge"]))
actions = list(dict.fromkeys(actions + ["?? ? ? ?? ???? ??? ???? ??? ?? ?? sidebar ?? ??? ? ???? grid/fixed-width ???? ?????."]))
actions = list(dict.fromkeys(actions + ["???? ??? ????? ??? ??? ????? ?? grid/fixed-width ??? ?? ????."]))
retry_plan = None
if status != "pass" and iteration < args.max_iterations:

View File

@@ -169,13 +169,29 @@ def _stage_1_5a(ctx: PipelineContext) -> PipelineContext:
}
slide_images = []
for img_key, img_info in (image_sizes or {}).items():
img_path = Path(ctx.base_path) / img_key if ctx.base_path else Path(img_key)
normalized_images = image_sizes or {}
if isinstance(normalized_images, list):
iterable = []
for item in normalized_images:
if not isinstance(item, dict):
continue
img_key = item.get('path') or item.get('src') or item.get('image_path') or ''
iterable.append((img_key, item))
else:
iterable = list(normalized_images.items())
for img_key, img_info in iterable:
if not img_key:
continue
cleaned_key = str(img_key).lstrip('/\\').replace('/', '\\')
img_path = Path(ctx.base_path) / cleaned_key if ctx.base_path else Path(img_key)
width = int(img_info.get('width', 0) or 0)
height = int(img_info.get('height', 0) or 0)
slide_images.append({
'path': str(img_path),
'width': img_info.get('width', 0),
'height': img_info.get('height', 0),
'ratio': round(img_info.get('width', 1) / max(1, img_info.get('height', 1)), 2),
'width': width,
'height': height,
'ratio': round((width or 1) / max(1, height or 1), 2),
'topic_id': img_info.get('topic_id'),
'b64': '',
})
@@ -493,7 +509,7 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
relation_bullets = _relation_bullets_from_raw(raw)[:4]
comparison_rows = _parse_comparison_rows_from_raw(raw)
preferred_axes = ['??', '????', '???', '???']
preferred_axes = ['\ubc94\uc704', '\ud504\ub85c\uc138\uc2a4', '\uc131\uacfc\ud488', '\ud655\uc7a5\uc131']
picked_rows = [row for row in comparison_rows if row[0] in preferred_axes]
if len(picked_rows) < 4:
seen = {row[0] for row in picked_rows}
@@ -520,18 +536,18 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
relation_len = sum(len(x) for x in relation_bullets)
sidebar_width = '34%' if defs_len >= relation_len else '31%'
main_width = '66%' if defs_len >= relation_len else '69%'
relation_visual_height = '210px' if intro_len > 320 else '230px'
relation_visual_height = '138px' if intro_len > 320 else '152px'
problem_items_html = ''.join(
f'<li style="margin-left:16px; margin-bottom:4px;">{_trim_visible_copy(item, floor=90, ceiling=220)}</li>'
f'<li style="margin-left:14px; margin-bottom:3px;">{_trim_visible_copy(item, floor=84, ceiling=180)}</li>'
for item in problem_bullets
)
evidence_items_html = ''.join(
f'<li style="margin-left:16px; margin-bottom:4px;">{_trim_visible_copy(item, floor=80, ceiling=180)}</li>'
f'<li style="margin-left:14px; margin-bottom:3px;">{_trim_visible_copy(item, floor=72, ceiling=150)}</li>'
for item in evidence_bullets
)
relation_items_html = ''.join(
f'<li style="margin-left:16px; margin-bottom:4px;">{_trim_visible_copy(item, floor=80, ceiling=210)}</li>'
f'<li style="margin-left:14px; margin-bottom:3px;">{_trim_visible_copy(item, floor=72, ceiling=150)}</li>'
for item in relation_bullets
)
@@ -547,42 +563,42 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
comparison_rows_html = ''
for axis, dx, bim in picked_rows:
comparison_rows_html += (
'<tr>'
f'<td style="border:1px solid #bfdbfe; padding:6px 8px; font-size:8px; line-height:1.4; color:#1e3a8a; width:42%;">{_trim_visible_copy(dx, floor=55, ceiling=120)}</td>'
f'<td style="border:1px solid #bfdbfe; padding:6px 8px; font-size:8px; line-height:1.4; font-weight:800; color:#0f172a; width:16%; text-align:center; background:#eff6ff;">{axis}</td>'
f'<td style="border:1px solid #bfdbfe; padding:6px 8px; font-size:8px; line-height:1.4; color:#334155; width:42%;">{_trim_visible_copy(bim, floor=55, ceiling=120)}</td>'
'</tr>'
'<div style="background:#ffffff; border:1px solid #bfdbfe; border-radius:10px; padding:8px 10px; display:flex; flex-direction:column; gap:4px; min-height:52px;">'
f'<div style="font-size:8px; font-weight:800; color:#1d4ed8;">{axis}</div>'
f'<div style="font-size:7.2px; line-height:1.32; color:#1e3a8a;"><span style="font-weight:700;">DX</span> {_trim_visible_copy(dx, floor=48, ceiling=92)}</div>'
f'<div style="font-size:7.2px; line-height:1.32; color:#334155;"><span style="font-weight:700;">BIM</span> {_trim_visible_copy(bim, floor=48, ceiling=92)}</div>'
'</div>'
)
intro_html = (
'<div style="background:linear-gradient(135deg,#fff7ed 0%,#ffedd5 100%); border:1px solid #fdba74; border-radius:12px; padding:10px 12px; display:grid; grid-template-columns:1fr 1fr; gap:12px;">'
f'<div><div style="font-size:12px; font-weight:800; color:#c2410c; margin-bottom:6px;">{problem_title}</div><ul style="font-size:10px; line-height:1.6; color:#7c2d12; padding-left:0; margin:0; list-style:disc;">{problem_items_html}</ul></div>'
f'<div><div style="font-size:12px; font-weight:800; color:#9a3412; margin-bottom:6px;">{evidence_title}</div><ul style="font-size:9px; line-height:1.55; color:#7c2d12; padding-left:0; margin:0; list-style:disc;">{evidence_items_html}</ul></div>'
'<div style="background:linear-gradient(135deg,#fff7ed 0%,#ffedd5 100%); border:1px solid #fdba74; border-radius:12px; padding:8px 10px; display:grid; grid-template-columns:1fr 1fr; gap:10px;">'
f'<div><div style="font-size:11px; font-weight:800; color:#c2410c; margin-bottom:4px;">{problem_title}</div><ul style="font-size:9px; line-height:1.45; color:#7c2d12; padding-left:0; margin:0; list-style:disc;">{problem_items_html}</ul></div>'
f'<div><div style="font-size:11px; font-weight:800; color:#9a3412; margin-bottom:4px;">{evidence_title}</div><ul style="font-size:8.5px; line-height:1.4; color:#7c2d12; padding-left:0; margin:0; list-style:disc;">{evidence_items_html}</ul></div>'
'</div>'
)
relation_html = (
f'<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:14px; padding:12px 14px; display:grid; grid-template-columns:280px 1fr; gap:12px;">'
'<div style="display:flex; flex-direction:column; gap:6px;">'
f'<div class="relation-diagram-card" style="background:#ffffff; border:1px solid #cbd5e1; border-radius:14px; padding:12px 14px; display:grid; grid-template-columns:250px 1fr; gap:10px;">'
'<div style="display:flex; flex-direction:column; gap:5px;">'
f'{_relation_visual(image_src, image_caption).replace("height:220px", f"height:{relation_visual_height}")}'
f'<div style="font-size:9px; line-height:1.4; color:#166534; background:#dcfce7; border:1px solid #86efac; border-radius:999px; padding:4px 8px; text-align:center;">{image_caption}</div>'
f'<div style="font-size:8px; line-height:1.3; color:#166534; background:#dcfce7; border:1px solid #86efac; border-radius:999px; padding:3px 8px; text-align:center;">{image_caption}</div>'
'</div>'
'<div style="display:flex; flex-direction:column; gap:8px;">'
f'<div style="font-size:12px; font-weight:800; color:#1e40af;">{relation_title}</div>'
f'<ul style="font-size:10px; line-height:1.6; color:#334155; padding-left:0; margin:0; list-style:disc;">{relation_items_html}</ul>'
'<div style="display:flex; flex-direction:column; gap:6px;">'
f'<div style="font-size:11px; font-weight:800; color:#1e40af;">{relation_title}</div>'
f'<ul style="font-size:8.5px; line-height:1.42; color:#334155; padding-left:0; margin:0; list-style:disc;">{relation_items_html}</ul>'
'</div>'
'</div>'
)
comparison_html = (
'<div style="background:#eff6ff; border:1px solid #bfdbfe; border-radius:12px; padding:8px 10px;">'
'<div class="comparison-summary-card" style="background:#eff6ff; border:1px solid #bfdbfe; border-radius:12px; padding:8px 10px;">'
f'<div style="font-size:11px; font-weight:800; color:#1d4ed8; margin-bottom:6px;">{comparison_title}</div>'
f'<table style="width:100%; border-collapse:collapse; table-layout:fixed;">{comparison_rows_html}</table>'
f'<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">{comparison_rows_html}</div>'
'</div>'
)
body_html = (
'<div style="width:100%; height:100%; box-sizing:border-box; font-family:\'Segoe UI\',sans-serif; color:#0f172a; display:flex; flex-direction:column; gap:8px;">'
'<div style="width:100%; height:100%; box-sizing:border-box; font-family:\'Segoe UI\',sans-serif; color:#0f172a; display:flex; flex-direction:column; gap:6px;">'
f'{intro_html}'
f'{relation_html}'
f'{comparison_html}'