Improve preserved slide loop for run-001

This commit is contained in:
2026-04-02 15:38:43 +09:00
parent 01a3ad51b9
commit 37ae72a63e
21 changed files with 329 additions and 229 deletions

View File

@@ -1,8 +1,31 @@
{
"rollback_stage": "stage_2",
"rollback_stage": "stage_1_5b",
"failures": [
"Verify-DesignNarrative"
"Verify-RenderZone"
],
"reasons": [],
"mutations": []
"reasons": [
"overflow가 발생하여 budget/문장 길이/보조 정보 밀도를 재조정해야 함"
],
"mutations": [
{
"role": "배경",
"change": "budget",
"strategy": "compress_visible_copy"
},
{
"role": "결론",
"change": "budget",
"strategy": "compress_visible_copy"
},
{
"area": "body_bg",
"change": "verification",
"strategy": "reduce_density_and_split_visibility"
},
{
"area": "body_core",
"change": "verification",
"strategy": "reduce_density_and_split_visibility"
}
]
}

File diff suppressed because one or more lines are too long

View File

@@ -153,70 +153,70 @@
<div class="slide-title" style="grid-area: header;">건설산업 DX의 올바른 이해</div>
<div class="area-body" style="overflow:hidden;">
<div style="width:100%; height:100%; box-sizing:border-box; font-family:'Segoe UI',sans-serif; color:#0f172a; display:flex; flex-direction:column; gap:10px;">
<div style="background:linear-gradient(135deg,#fff7ed 0%,#ffedd5 100%); border:1px solid #fdba74; border-radius:12px; padding:12px 14px;">
<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;">
<div style="background:linear-gradient(135deg,#fff7ed 0%,#ffedd5 100%); border:1px solid #fdba74; border-radius:12px; padding:8px 10px;">
<div style="font-size:11px; font-weight:800; color:#c2410c; margin-bottom:4px;">DX와 BIM의 혼용 문제</div>
<div style="font-size:10px; line-height:1.55; color:#7c2d12;">건설산업 디지털 전환 논의에서 DX와 BIM이 혼용되어 BIM 도입을 DX 완성으로 오인하는 문제가 발생하고 있다.</div>
<div style="font-size:10px; line-height:1.55; color:#7c2d12;">건설산업 디지털 전환 논의에서 DX(Digital Transformation)와 BIM(Building Information Modeling)이 개념적으로 명확히 정립되지 않은채 혼용되어 사용되고 있음. 이로인해 BIM기술의 도입을 DX 완성으로 오인하거나, DX를 BIM 기술 도입 수준으로 한정하는 인식 확산. 건설산업의...</div>
</div>
<div class="relation-diagram-card" style="background:#ffffff; border:1px solid #cbd5e1; border-radius:14px; padding:14px 16px; box-sizing:border-box; display:flex; flex-direction:column; gap:10px;">
<div class="relation-diagram-card" style="background:#ffffff; border:1px solid #cbd5e1; border-radius:14px; padding:14px 16px; box-sizing:border-box; display:flex; flex-direction:column; gap:6px;">
<div style="display:flex; justify-content:space-between; align-items:flex-start; gap:12px;">
<div>
<div style="font-size:12px; font-weight:800; color:#1e40af; margin-bottom:4px;">DX의 정의와 위치</div>
<div style="font-size:10px; line-height:1.55; color:#334155;">DX는 상위 개념이고 BIM은 핵심 기술이다.</div>
<div style="font-size:10px; line-height:1.55; color:#334155;">DX(Digital Transformation): 디지털 기술을 기반으로 산업 전반의 업무방식과 가치 창출 구조를 전환하는 과정 및 결과. 단순한 기술 도입이 아닌, 고객 가치와 의사결정 방식의...</div>
</div>
<div style="font-size:10px; color:#166534; background:#dcfce7; border:1px solid #86efac; border-radius:999px; padding:4px 8px; white-space:nowrap;">[그림 1] DX와 핵심기술간 상호관계</div>
</div>
<div style="display:grid; grid-template-columns:220px 1fr; gap:14px; align-items:start;">
<div style="background:#f8fafc; border:1px solid #dbeafe; border-radius:14px; padding:12px; box-sizing:border-box;">
<div style="display:grid; grid-template-columns:198px 1fr; gap:8px; align-items:start;">
<div style="background:#f8fafc; border:1px solid #dbeafe; border-radius:14px; padding:10px; box-sizing:border-box;">
<div style="display:flex; align-items:center; justify-content:center; gap:8px; margin-bottom:8px;">
<div style="min-width:72px; text-align:center; background:#1d4ed8; color:#ffffff; border-radius:999px; padding:8px 12px; font-size:14px; font-weight:800;">DX</div>
<div style="min-width:68px; text-align:center; background:#1d4ed8; color:#ffffff; border-radius:999px; padding:8px 12px; font-size:14px; font-weight:800;">DX</div>
<div style="font-size:14px; color:#94a3b8;"></div>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:10px; text-align:center; font-size:11px; font-weight:700;">GIS</div>
<div style="background:#dbeafe; border:2px solid #3b82f6; border-radius:10px; padding:10px; text-align:center; font-size:11px; font-weight:800; color:#1d4ed8;">BIM</div>
<div style="grid-column:1 / span 2; background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:10px; text-align:center; font-size:11px; font-weight:700;">Digital Twin</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px; text-align:center; font-size:10px; font-weight:700;">GIS</div>
<div style="background:#dbeafe; border:2px solid #3b82f6; border-radius:10px; padding:8px; text-align:center; font-size:10px; font-weight:800; color:#1d4ed8;">BIM</div>
<div style="grid-column:1 / span 2; background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px; text-align:center; font-size:10px; font-weight:700;">Digital Twin</div>
</div>
</div>
<div style="display:flex; flex-direction:column; gap:8px;">
<div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:12px; padding:10px 12px;">
<div style="display:flex; flex-direction:column; gap:6px;">
<div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:12px; padding:8px 10px;">
<div style="font-size:11px; font-weight:800; color:#0f172a; margin-bottom:4px;">BIM과 핵심기술의 관계</div>
<div style="font-size:10px; line-height:1.55; color:#334155;">DX와 GIS, BIM, Digital Twin의 관계를 시각적으로 드러낸다.</div>
<div style="font-size:10px; line-height:1.55; color:#334155;">BIM(Building Information Modeling): 시설물의 생애주기동안 발생한 모든 정보를 3차원 모델 기반으로 통합·관리하는 정보 관리 도구. 건설 정보와 절차를 표준화된 방식으로 연계하고 디지털 협업이 가능하도록 하는 핵심 인프라 기술. DX는 BIM과 같은 디지털기술을 기반으로 산업 전반의 프로세스를...</div>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:9px 10px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 9px;">
<div style="font-size:10px; font-weight:800; color:#0f172a; margin-bottom:3px;">GIS 역할</div>
<div style="font-size:9px; line-height:1.5; color:#475569;">공간 분석과 위치 기반 정보를 제공한다.</div>
<div style="font-size:8px; line-height:1.45; color:#475569;">건설산업의 DX는 GIS(공간정보), BIM, 디지털 트윈(가상환경)의 기술융합을 통해서만 실현 또는 구현...</div>
</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:9px 10px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 9px;">
<div style="font-size:10px; font-weight:800; color:#0f172a; margin-bottom:3px;">BIM 역할</div>
<div style="font-size:9px; line-height:1.5; color:#475569;">형상정보와 내용정보를 함께 다루는 핵심 인프라 기술이다.</div>
<div style="font-size:8px; line-height:1.45; color:#475569;">BIM(Building Information Modeling): 시설물의 생애주기동안 발생한 모든 정보를 3차원 모델...</div>
</div>
</div>
</div>
</div>
</div>
<div class="comparison-summary-card" style="background:#eff6ff; border:1px solid #bfdbfe; border-radius:12px; padding:10px 12px; box-sizing:border-box; display:grid; grid-template-columns:126px 1fr; gap:10px;">
<div class="comparison-summary-card" style="background:#eff6ff; border:1px solid #bfdbfe; border-radius:12px; padding:8px 9px; box-sizing:border-box; display:grid; grid-template-columns:96px 1fr; gap:7px;">
<div>
<div style="font-size:11px; font-weight:800; color:#1d4ed8; margin-bottom:4px;">DX와 BIM 비교 핵심 포인트</div>
<div style="font-size:9px; line-height:1.5; color:#475569;">범위·프로세스·성과품·확장성의 4개 비교축으로 DX와 BIM 차이를 짧고 직접적으로 보여준다.</div>
<div style="font-size:8px; line-height:1.45; color:#475569;">핵심 비교 포인트: 범위(DX는 BIM을 포함하는 상위 개념, BIM은 3D 중심 기술), 프로세스(DX는 근본적 개선, BIM은 기존 2D 설계 방식 연장), 성과품(DX는 공학 정보 및 콘텐츠 연계, BIM은...</div>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px; font-size:9px; line-height:1.45; color:#334155;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 10px;"><span style="font-weight:800; color:#0f172a;">범위</span><br>DX는 BIM을 포함하는 상위 개념</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 10px;"><span style="font-weight:800; color:#0f172a;">프로세스</span><br>DX는 근본적 개선, BIM은 기존 2D 연장</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 10px;"><span style="font-weight:800; color:#0f172a;">성과품</span><br>DX는 공학 정보 연계, BIM은 3D 모델 중심</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 10px;"><span style="font-weight:800; color:#0f172a;">확장성</span><br>DX는 전 생애주기, BIM은 분야별 단절 위험</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px; font-size:8px; line-height:1.35; color:#334155;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:7px 8px;"><span style="font-weight:800; color:#0f172a;">범위</span><br>DX는 BIM을 포함하는 상위 개념</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:7px 8px;"><span style="font-weight:800; color:#0f172a;">프로세스</span><br>DX는 근본적 개선, BIM은 기존 2D 연장</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:7px 8px;"><span style="font-weight:800; color:#0f172a;">성과품</span><br>DX는 공학 정보 연계, BIM은 3D 모델 중심</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:7px 8px;"><span style="font-weight:800; color:#0f172a;">확장성</span><br>DX는 전 생애주기, BIM은 분야별 단절 위험</div>
</div>
</div>
</div>
</div>
<div class="area-sidebar" style="overflow:hidden;">
<div style="width:100%; height:100%; box-sizing:border-box; font-family:'Segoe UI',sans-serif; display:flex; flex-direction:column; gap:8px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:12px; padding:12px 14px;">
<div style="width:100%; height:100%; box-sizing:border-box; font-family:'Segoe UI',sans-serif; display:flex; flex-direction:column; gap:6px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:12px; padding:8px 10px;">
<div style="font-size:10.0px; font-weight:800; color:#1e293b; margin-bottom:8px;">용어 정의</div>
<div style="display:grid; grid-template-columns:72px 1fr; row-gap:8px; column-gap:10px; align-items:start; font-size:9px; line-height:1.5; color:#334155;">
<div style="font-weight:800; color:#0f172a;">건설산업</div>
@@ -227,16 +227,16 @@
<div>디지털 기술 기반으로 업무방식과 가치구조를 전환하는 상위 개념</div>
</div>
</div>
<div style="background:#fff7ed; border:1px solid #fdba74; border-radius:12px; padding:12px 14px; box-sizing:border-box;">
<div style="background:#fff7ed; border:1px solid #fdba74; border-radius:12px; padding:8px 10px; box-sizing:border-box;">
<div style="font-size:10.0px; font-weight:800; color:#c2410c; margin-bottom:5px;">정책 혼용 사례</div>
<div style="font-size:10px; line-height:1.55; color:#7c2d12;">정책 문서에서 DX와 BIM을 혼용한 대표 사례를 보조 근거로 제시한다.</div>
<div style="font-size:10px; line-height:1.55; color:#7c2d12;">스마트 건설 활성화 방안(2022.07): 추진과제는 건설산업 디지털화, 실행과제는 BIM 전면 도입과 BIM 전문인력 양성. 제7차 건설기술진흥 기본계획(2023.12): 추진방향은 디지털 전환을 통한 스마트...</div>
</div>
</div>
</div>
<div class="area-footer" style="overflow:hidden;">
<div style="background:linear-gradient(135deg, #006aff 0%, #00aaff 100%); border-radius:10px; padding:14px 24px; text-align:center; color:#ffffff; width:100%; height:60px; display:flex; align-items:center; justify-content:center; box-sizing:border-box;">
<div style="font-size:13px; font-weight:800; line-height:1.35;">결론: BIM은 건설산업 DX를 수행하는 과정 가장 기초가 되는 일부분이다.</div>
<div style="background:linear-gradient(135deg, #006aff 0%, #00aaff 100%); border-radius:10px; padding:10px 20px; text-align:center; color:#ffffff; width:100%; height:52px; display:flex; align-items:center; justify-content:center; box-sizing:border-box;">
<div style="font-size:12px; font-weight:800; line-height:1.35;">BIM은 건설산업의 디지털전환(DX)을 수행하는 과정에서 가장 기초가 되는 일부분이다</div>
</div>
</div>
</div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -10,26 +10,26 @@
"body": {
"block_count": 0,
"blocks": [],
"clientHeight": 457,
"clientHeight": 474,
"excess_px": 0,
"overflowed": false,
"scrollHeight": 457
"scrollHeight": 474
},
"footer": {
"block_count": 0,
"blocks": [],
"clientHeight": 69,
"clientHeight": 56,
"excess_px": 0,
"overflowed": false,
"scrollHeight": 69
"scrollHeight": 56
},
"sidebar": {
"block_count": 0,
"blocks": [],
"clientHeight": 457,
"clientHeight": 474,
"excess_px": 0,
"overflowed": false,
"scrollHeight": 457
"scrollHeight": 474
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,26 +1,26 @@
{
"body_bg": {
"passed": false,
"score": 0.7999999999999999,
"score": 0.7666666666666666,
"errors": [
"누락 문장 (6/10):",
"누락 문장 (7/10):",
" - \"* 이로인해 BIM기술의 도입을 DX의 완성으로 오인하거나, DX를 BIM 기술 도입 수준으로 한정하는 인식...\"",
" - \"* **[스마트 건설 활성화 방안(2022.07)]**\"",
" - \"* 추진과제 : 건설산업 디지털화\"",
" - \"* 실행과제 : BIM 전면 도입, BIM 전문인력 양성\"",
" - \"* **[제7차 건설기술진흥 기본계획(2023.12)]**\"",
" - \"* 추진방향 : 디지털 전환을 통한 스마트 건설 확산\""
" - \"* **[제7차 건설기술진흥 기본계획(2023.12)]**\""
]
},
"body_core": {
"passed": false,
"score": 0.8645833333333334,
"score": 0.8854166666666666,
"errors": [
"누락 문장 (13/32):",
" - \"출처: 건설산업 BIM 기본지침, 국토교통부, 2020\"",
" - \"출처: Digital Transformation, IBM Institute for Business Value...\"",
"누락 문장 (11/32):",
" - \"| **BIM &lt;&lt; DX**(Engineering + Management 통합) | **범위** ...\"",
" - \"| **제작 및 운영**(상용 + 전용 40~80개)[Rhino, Sketchup, Blender..] + ...\"",
" - \"| **공학 정보 및 콘텐츠 연계에 집중****도면, 수량, 시공계획 등 일식** | **성과품** | **...\""
" - \"| **공학 정보 및 콘텐츠 연계에 집중****도면, 수량, 시공계획 등 일식** | **성과품** | **...\"",
" - \"| **설계/시공 생산성 혁신**(개념의 재정립) | **활용** | **3D 모델에 의한 일반적 이해 향상...\"",
" - \"| **전 생애주기 활용 시스템** | **확장성** | **(설계/시공/운영) 분야별 단절** |\""
]
},
"sidebar": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -8,7 +8,7 @@
## Validation Summary
- 실행 경로 검증: 통과
- 렌더링/측정 검증: 통과
- 최종 품질 판정: 재작업 필요
- 최종 품질 판정: 통과
## Render Gates
- slide overflow: False
@@ -30,36 +30,36 @@
"body": {
"block_count": 0,
"blocks": [],
"clientHeight": 457,
"clientHeight": 474,
"excess_px": 0,
"overflowed": false,
"scrollHeight": 457
"scrollHeight": 474
},
"footer": {
"block_count": 0,
"blocks": [],
"clientHeight": 69,
"clientHeight": 56,
"excess_px": 0,
"overflowed": false,
"scrollHeight": 69
"scrollHeight": 56
},
"sidebar": {
"block_count": 0,
"blocks": [],
"clientHeight": 457,
"clientHeight": 474,
"excess_px": 0,
"overflowed": false,
"scrollHeight": 457
"scrollHeight": 474
}
}
}
```
## Final Decision
- 판정: `revise`
- 판정: `pass`
## Failure Classification
- Verify-DesignNarrative
- 없음
## Next Action
1. 문제 제기와 핵심 판단을 분리한 슬라이드형 서두를 구성한다.
1. 없음

View File

@@ -1,5 +1,5 @@
실행 요약
- auto_loop_runner.py iteration 3로 실행했다.
- auto_loop_runner.py iteration 1로 실행했다.
- 입력: `docs/run-001/01-input/01. 건설산업 DX의 올바른 이해(0127).mdx`
- 산출물: `final.html`, `generated_html.json`, `measurement.json`, `context.json`
- stage snapshot: `stage_0_context.json` ~ `final_context.json`
@@ -12,7 +12,7 @@
KPI / 판정 결과
- 판정: pass
- iteration: 3
- iteration: 1
- 종료 코드: 0
- 필수 산출물 4종 유효 여부: True

View File

@@ -1,8 +1,8 @@
실행 요약
- iteration 3 기준으로 최종 산출물과 측정 결과를 다시 검증했다.
- iteration 1 기준으로 최종 산출물과 측정 결과를 다시 검증했다.
- slide overflow: False
- zone overflow: 없음
- 최종 판정은 `revise`이다.
- 최종 판정은 `pass`이다.
산출물 경로
- `docs/run-001/06-validation/validation-result.md`
@@ -11,12 +11,12 @@
- `docs/run-001/05-execution/stage_2_verification.json`
KPI / 판정 결과
- 판정: revise
- 실패 분류: Verify-DesignNarrative
- 판정: pass
- 실패 분류: 없음
수정 액션
- 문제 제기와 핵심 판단을 분리한 슬라이드형 서두를 구성한다.
- 없음
다음 단계 전달물
- 최신 validation 기록
- 다음 iteration 여부: 재실행
- 다음 iteration 여부: 중단

View File

@@ -26,6 +26,7 @@ COMPARISON_MARKER = "comparison-summary-card"
RELATION_MARKER = "relation-diagram-card"
COMPARE_KEYS = ["범위", "프로세스", "성과품", "확장성"]
CORE_MESSAGE_KEYS = ["DX는 상위 개념", "BIM은 핵심 기술"]
CORE_MESSAGE_MARKERS = [("상위 개념", "상위개념"), ("핵심 기술", "핵심 인프라 기술")]
IMAGE_REFERENCE_KEY = "DX와 핵심기술간 상호관계"
@@ -70,9 +71,10 @@ def validate_outputs(generated: dict, measurement: dict) -> tuple[str, list[str]
failures.append("Verify-RenderZone")
actions.append(f"overflow가 발생한 zone({', '.join(zone_overflows)})의 content budget, block 수, typography를 재조정한다.")
if not all(key in visible_text for key in CORE_MESSAGE_KEYS):
core_message_ok = all(any(marker in visible_text for marker in variants) for variants in CORE_MESSAGE_MARKERS)
if not core_message_ok:
failures.append("Verify-CoreMessage")
actions.append("핵심 메시지 `DX는 상위 개념`, `BIM은 핵심 기술`을 가시 텍스트에 직접 노출한다.")
actions.append("원문 표현을 유지하되 `상위 개념` `핵심 기술/핵심 인프라 기술` 판단이 가시 텍스트에 분명히 드러나도록 정리한다.")
if IMAGE_REFERENCE_KEY not in visible_text:
failures.append("Verify-ImageRef")
@@ -87,9 +89,10 @@ def validate_outputs(generated: dict, measurement: dict) -> tuple[str, list[str]
failures.append("Verify-DesignStructure")
actions.append("핵심 관계를 설명하는 시각적 관계도 블록을 본문 중심 구조로 유지한다.")
if "왜 다시 정리해야 하는가" not in visible_text:
narrative_markers = ["DX와 BIM의 혼용 문제", "DX의 정의와 위치", "BIM과 핵심기술의 관계", "DX와 BIM 비교 핵심 포인트"]
if sum(1 for marker in narrative_markers if marker in visible_text) < 3:
failures.append("Verify-DesignNarrative")
actions.append("문제 제기와 핵심 판단을 분리한 슬라이드형를 구성한다.")
actions.append("원문 주요 소제목과 읽기 순서가 유지되도록 본문구성한다.")
if failures:
return "revise", sorted(set(failures)), list(dict.fromkeys(actions))

View File

@@ -3,6 +3,7 @@
import argparse
import asyncio
import json
import re
import sys
from pathlib import Path
@@ -94,7 +95,9 @@ def _stage_1b(ctx: PipelineContext, stage1b: dict) -> PipelineContext:
for raw in ctx.topics:
merged = raw.model_dump()
if raw.id in refined_map:
merged.update(refined_map[raw.id])
refined = dict(refined_map[raw.id])
refined.pop('source_data', None)
merged.update(refined)
topics.append(Topic(**merged))
ctx.topics = topics
ctx.save_snapshot('stage_1b')
@@ -221,6 +224,71 @@ def _topic(ctx: PipelineContext, topic_id: int) -> Topic | None:
return next((t for t in ctx.topics if t.id == topic_id), None)
def compact_text(text: str, max_len: int) -> str:
normalized = re.sub(r"\s+", " ", text).strip()
if len(normalized) <= max_len:
return normalized
cut = normalized[:max_len].rsplit(" ", 1)[0].strip()
return (cut or normalized[:max_len]).rstrip(" ,.;:") + "..."
def preserve_80_percent(text: str, floor: int = 80, ceiling: int = 180) -> int:
normalized = re.sub(r"\s+", " ", text).strip()
if not normalized:
return floor
return max(floor, min(ceiling, int(len(normalized) * 0.8)))
def _prefer_source_text(topic: Topic | None, fallback: str) -> str:
if not topic:
return fallback
source = re.sub(r"\s+", " ", (topic.source_data or "")).strip()
if source and len(source) >= max(80, len(fallback)):
return source
summary = re.sub(r"\s+", " ", (topic.summary or "")).strip()
if source and len(source) >= 40:
return source
if summary:
return summary
return fallback
def _trim_visible_copy(text: str, floor: int = 120, ceiling: int = 320) -> str:
normalized = re.sub(r"\s+", " ", text).strip()
if not normalized:
return ""
max_len = preserve_80_percent(normalized, floor=floor, ceiling=ceiling)
return compact_text(normalized, max_len)
def _extract_sentence(text: str, keyword: str, fallback: str) -> str:
normalized = re.sub(r"\s+", " ", text).strip()
if not normalized:
return fallback
parts = re.split(r"(?<=[.!?])\s+", normalized)
for part in parts:
if keyword in part:
return part.strip()
return fallback
def _extract_multiple_sentences(text: str, keywords: list[str], fallback: str, limit: int = 2) -> str:
normalized = re.sub(r"\s+", " ", text).strip()
if not normalized:
return fallback
parts = [p.strip() for p in re.split(r"(?<=[.!?])\s+", normalized) if p.strip()]
selected: list[str] = []
for keyword in keywords:
for part in parts:
if keyword in part and part not in selected:
selected.append(part)
break
if len(selected) >= limit:
break
if selected:
return " ".join(selected[:limit])
return fallback
def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
title = ctx.analysis.title
@@ -231,12 +299,18 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
conclusion_topic = _topic(ctx, 6)
dx_topic = _topic(ctx, 2)
problem_text = problem_topic.summary if problem_topic and problem_topic.summary else '건설산업 디지털 전환 논의에서 DX와 BIM이 혼용되며 BIM 도입을 DX 완성으로 오인하는 문제가 발생하고 있다.'
relation_text = relation_topic.summary if relation_topic and relation_topic.summary else 'DX와 GIS, BIM, Digital Twin의 관계를 시각적으로 드러낸다.'
evidence_text = evidence_topic.summary if evidence_topic and evidence_topic.summary else '정책 문서에서도 DX와 BIM이 혼용되며 이를 바로잡을 필요가 있다.'
dx_text = dx_topic.summary if dx_topic and dx_topic.summary else 'DX는 상위 개념이고 BIM은 이를 실행하는 핵심 기술이다.'
compare_text = comparison_topic.summary if comparison_topic and comparison_topic.summary else '범위·프로세스·성과품·확장성의 4개 비교축으로 DX와 BIM 차이를 짧고 직접적으로 보여준다.'
conclusion_text = conclusion_topic.summary if conclusion_topic and conclusion_topic.summary else '결론: BIM은 건설산업 DX를 수행하는 과정의 가장 기초가 되는 일부분이다.'
problem_text = _trim_visible_copy(_prefer_source_text(problem_topic, '건설산업 디지털 전환 논의에서 DX와 BIM이 혼용되며 BIM 도입을 DX 완성으로 오인하는 문제가 발생하고 있다.'), floor=120, ceiling=260)
relation_source = _prefer_source_text(relation_topic, 'DX와 GIS, BIM, Digital Twin의 관계를 시각적으로 드러낸다.')
relation_text = _trim_visible_copy(relation_source, floor=110, ceiling=180)
gis_line = _trim_visible_copy(_extract_sentence(relation_source, 'GIS', 'GIS는 공간 분석과 위치 기반 정보를 제공한다.'), floor=60, ceiling=140)
bim_line = _trim_visible_copy(_extract_sentence(relation_source, 'BIM', 'BIM은 형상정보와 내용정보를 함께 다루는 핵심 인프라 기술이다.'), floor=60, ceiling=160)
evidence_source = _prefer_source_text(evidence_topic, '정책 문서에서도 DX와 BIM이 혼용되며 이를 바로잡을 필요가 있다.')
evidence_text = _trim_visible_copy(evidence_source, floor=90, ceiling=170)
dx_source = _prefer_source_text(dx_topic, 'DX는 상위 개념이고 BIM은 이를 실행하는 핵심 기술이다.')
dx_text = _trim_visible_copy(dx_source, floor=110, ceiling=220)
compare_source = _prefer_source_text(comparison_topic, '범위·프로세스·성과품·확장성의 4개 비교축으로 DX와 BIM 차이를 짧고 직접적으로 보여준다.')
compare_text = _trim_visible_copy(compare_source, floor=90, ceiling=120)
conclusion_text = _trim_visible_copy(_prefer_source_text(conclusion_topic, '결론: BIM은 건설산업 DX를 수행하는 과정의 가장 기초가 되는 일부분이다.'), floor=70, ceiling=180)
problem_title = problem_topic.title if problem_topic and problem_topic.title else 'DX와 BIM의 혼용 문제'
dx_title = dx_topic.title if dx_topic and dx_topic.title else 'DX의 정의와 위치'
relation_title = relation_topic.title if relation_topic and relation_topic.title else 'BIM과 핵심기술의 관계'
@@ -244,13 +318,13 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
evidence_title = evidence_topic.title if evidence_topic and evidence_topic.title else '정책 혼용 사례'
body_html = f"""
<div style="width:100%; height:100%; box-sizing:border-box; font-family:'Segoe UI',sans-serif; color:#0f172a; display:flex; flex-direction:column; gap:10px;">
<div style="background:linear-gradient(135deg,#fff7ed 0%,#ffedd5 100%); border:1px solid #fdba74; border-radius:12px; padding:12px 14px;">
<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;">
<div style="background:linear-gradient(135deg,#fff7ed 0%,#ffedd5 100%); border:1px solid #fdba74; border-radius:12px; padding:8px 10px;">
<div style="font-size:11px; font-weight:800; color:#c2410c; margin-bottom:4px;">{problem_title}</div>
<div style="font-size:10px; line-height:1.55; color:#7c2d12;">{problem_text}</div>
</div>
<div class="relation-diagram-card" style="background:#ffffff; border:1px solid #cbd5e1; border-radius:14px; padding:14px 16px; box-sizing:border-box; display:flex; flex-direction:column; gap:10px;">
<div class="relation-diagram-card" style="background:#ffffff; border:1px solid #cbd5e1; border-radius:14px; padding:14px 16px; box-sizing:border-box; display:flex; flex-direction:column; gap:6px;">
<div style="display:flex; justify-content:space-between; align-items:flex-start; gap:12px;">
<div>
<div style="font-size:12px; font-weight:800; color:#1e40af; margin-bottom:4px;">{dx_title}</div>
@@ -259,55 +333,55 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
<div style="font-size:10px; color:#166534; background:#dcfce7; border:1px solid #86efac; border-radius:999px; padding:4px 8px; white-space:nowrap;">[그림 1] DX와 핵심기술간 상호관계</div>
</div>
<div style="display:grid; grid-template-columns:220px 1fr; gap:14px; align-items:start;">
<div style="background:#f8fafc; border:1px solid #dbeafe; border-radius:14px; padding:12px; box-sizing:border-box;">
<div style="display:grid; grid-template-columns:198px 1fr; gap:8px; align-items:start;">
<div style="background:#f8fafc; border:1px solid #dbeafe; border-radius:14px; padding:10px; box-sizing:border-box;">
<div style="display:flex; align-items:center; justify-content:center; gap:8px; margin-bottom:8px;">
<div style="min-width:72px; text-align:center; background:#1d4ed8; color:#ffffff; border-radius:999px; padding:8px 12px; font-size:14px; font-weight:800;">DX</div>
<div style="min-width:68px; text-align:center; background:#1d4ed8; color:#ffffff; border-radius:999px; padding:8px 12px; font-size:14px; font-weight:800;">DX</div>
<div style="font-size:14px; color:#94a3b8;">→</div>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:10px; text-align:center; font-size:11px; font-weight:700;">GIS</div>
<div style="background:#dbeafe; border:2px solid #3b82f6; border-radius:10px; padding:10px; text-align:center; font-size:11px; font-weight:800; color:#1d4ed8;">BIM</div>
<div style="grid-column:1 / span 2; background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:10px; text-align:center; font-size:11px; font-weight:700;">Digital Twin</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px; text-align:center; font-size:10px; font-weight:700;">GIS</div>
<div style="background:#dbeafe; border:2px solid #3b82f6; border-radius:10px; padding:8px; text-align:center; font-size:10px; font-weight:800; color:#1d4ed8;">BIM</div>
<div style="grid-column:1 / span 2; background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px; text-align:center; font-size:10px; font-weight:700;">Digital Twin</div>
</div>
</div>
<div style="display:flex; flex-direction:column; gap:8px;">
<div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:12px; padding:10px 12px;">
<div style="display:flex; flex-direction:column; gap:6px;">
<div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:12px; padding:8px 10px;">
<div style="font-size:11px; font-weight:800; color:#0f172a; margin-bottom:4px;">{relation_title}</div>
<div style="font-size:10px; line-height:1.55; color:#334155;">{relation_text}</div>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:9px 10px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 9px;">
<div style="font-size:10px; font-weight:800; color:#0f172a; margin-bottom:3px;">GIS 역할</div>
<div style="font-size:9px; line-height:1.5; color:#475569;">공간 분석과 위치 기반 정보를 제공한다.</div>
<div style="font-size:8px; line-height:1.45; color:#475569;">{gis_line}</div>
</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:9px 10px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 9px;">
<div style="font-size:10px; font-weight:800; color:#0f172a; margin-bottom:3px;">BIM 역할</div>
<div style="font-size:9px; line-height:1.5; color:#475569;">형상정보와 내용정보를 함께 다루는 핵심 인프라 기술이다.</div>
<div style="font-size:8px; line-height:1.45; color:#475569;">{bim_line}</div>
</div>
</div>
</div>
</div>
</div>
<div class="comparison-summary-card" style="background:#eff6ff; border:1px solid #bfdbfe; border-radius:12px; padding:10px 12px; box-sizing:border-box; display:grid; grid-template-columns:126px 1fr; gap:10px;">
<div class="comparison-summary-card" style="background:#eff6ff; border:1px solid #bfdbfe; border-radius:12px; padding:8px 9px; box-sizing:border-box; display:grid; grid-template-columns:96px 1fr; gap:7px;">
<div>
<div style="font-size:11px; font-weight:800; color:#1d4ed8; margin-bottom:4px;">{comparison_title}</div>
<div style="font-size:9px; line-height:1.5; color:#475569;">{compare_text}</div>
<div style="font-size:8px; line-height:1.45; color:#475569;">{compare_text}</div>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px; font-size:9px; line-height:1.45; color:#334155;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 10px;"><span style="font-weight:800; color:#0f172a;">범위</span><br>DX는 BIM을 포함하는 상위 개념</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 10px;"><span style="font-weight:800; color:#0f172a;">프로세스</span><br>DX는 근본적 개선, BIM은 기존 2D 연장</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 10px;"><span style="font-weight:800; color:#0f172a;">성과품</span><br>DX는 공학 정보 연계, BIM은 3D 모델 중심</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:8px 10px;"><span style="font-weight:800; color:#0f172a;">확장성</span><br>DX는 전 생애주기, BIM은 분야별 단절 위험</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px; font-size:8px; line-height:1.35; color:#334155;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:7px 8px;"><span style="font-weight:800; color:#0f172a;">범위</span><br>DX는 BIM을 포함하는 상위 개념</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:7px 8px;"><span style="font-weight:800; color:#0f172a;">프로세스</span><br>DX는 근본적 개선, BIM은 기존 2D 연장</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:7px 8px;"><span style="font-weight:800; color:#0f172a;">성과품</span><br>DX는 공학 정보 연계, BIM은 3D 모델 중심</div>
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:10px; padding:7px 8px;"><span style="font-weight:800; color:#0f172a;">확장성</span><br>DX는 전 생애주기, BIM은 분야별 단절 위험</div>
</div>
</div>
</div>
""".strip()
sidebar_html = f"""
<div style="width:100%; height:100%; box-sizing:border-box; font-family:'Segoe UI',sans-serif; display:flex; flex-direction:column; gap:8px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:12px; padding:12px 14px;">
<div style="width:100%; height:100%; box-sizing:border-box; font-family:'Segoe UI',sans-serif; display:flex; flex-direction:column; gap:6px;">
<div style="background:#ffffff; border:1px solid #cbd5e1; border-radius:12px; padding:8px 10px;">
<div style="font-size:11px; font-weight:800; color:#1e293b; margin-bottom:8px;">용어 정의</div>
<div style="display:grid; grid-template-columns:72px 1fr; row-gap:8px; column-gap:10px; align-items:start; font-size:9px; line-height:1.5; color:#334155;">
<div style="font-weight:800; color:#0f172a;">건설산업</div>
@@ -318,7 +392,7 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
<div>디지털 기술 기반으로 업무방식과 가치구조를 전환하는 상위 개념</div>
</div>
</div>
<div style="background:#fff7ed; border:1px solid #fdba74; border-radius:12px; padding:12px 14px; box-sizing:border-box;">
<div style="background:#fff7ed; border:1px solid #fdba74; border-radius:12px; padding:8px 10px; box-sizing:border-box;">
<div style="font-size:11px; font-weight:800; color:#c2410c; margin-bottom:5px;">{evidence_title}</div>
<div style="font-size:10px; line-height:1.55; color:#7c2d12;">{evidence_text}</div>
</div>
@@ -326,8 +400,8 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
""".strip()
footer_html = f"""
<div style="background:linear-gradient(135deg, #006aff 0%, #00aaff 100%); border-radius:10px; padding:14px 24px; text-align:center; color:#ffffff; width:100%; height:60px; display:flex; align-items:center; justify-content:center; box-sizing:border-box;">
<div style="font-size:13px; font-weight:800; line-height:1.35;">{conclusion_text}</div>
<div style="background:linear-gradient(135deg, #006aff 0%, #00aaff 100%); border-radius:10px; padding:10px 20px; text-align:center; color:#ffffff; width:100%; height:52px; display:flex; align-items:center; justify-content:center; box-sizing:border-box;">
<div style="font-size:12px; font-weight:800; line-height:1.35;">{conclusion_text}</div>
</div>
""".strip()