UnifiedComposer (Opus 4.7) 가 분석·본문·차트·지도까지 모두 단일 호출로 emit. 외부 결정적 빌더와 maplibre 의존을 폐기하고 mono guide 정합으로 통일. 보고서 자유도 + 시각화 자유도가 한 LLM 의 판단으로 수렴.
입력: 텔레그램에 사건 한 줄. 심층/짧게/요약 키워드로 모드 자동 결정. 모든 모드 LLM 호출 2회.
처리: 1) 상황 분석관 (Opus 4.7, 웹 검색) — 사실 / 타임라인 / 핵심 수치 / 출처 URL 수집 → 2) 편집장 (Opus 4.7, 단일 호출) — 행위자 / 구조 / 시나리오 / 모순 분석 + 보고서 본문 + 감시 신호 + 차트 8종 데이터 + 지도 데이터 모두 emit → 3) HTML 렌더 + Cloudflare Pages 배포.
v4.0.0~v4.1.0 vs v4.2.0 차이: 이전엔 차트/지도가 전혀 안 박혔음 (composer 가 chart-id referencing 해도 chart_payload 가 비어있어 매칭 실패). v4.2.0 에서 composer 가 차트 데이터를 직접 dict 로 emit, charts.js 가 inline payload 로 렌더. 지도도 composer 가 lat/lng 직접 emit, maplibre 폐기하고 d3 + d3-geo + TopoJSON 으로 통일.
핵심 안전장치: 수치 비교가 본문 이해에 결정적일 때만 차트 emit (composer 시스템 프롬프트). 데이터 없으면 차트 0개. 무지성 박힘 영구 차단.
v3.5.0 까지 5~13단계 + 차트는 결정적 빌더 자동 추출. v4.2.0 부터 4단계 + 차트/지도 모두 composer 가 직접 emit.
이전 v3.x 의 결정적 빌더 (build_chart_payload) 는 분석 결과 데이터에서 9종 차트를 자동 추출. 왜 그 차트를 박는지 (= 본문에서 referencing 하는지) 와 데이터 추출이 분리되어 있어 무관한 차트가 양산됨. v4.2.0 은 둘을 합침 — composer 가 본문을 짜면서 "이 단락은 도넛으로 보여주는 게 결정적" 이라고 판단할 때만 차트 emit. 외부 빌더 0줄.
ComposedReport 를 freeform_essay.html 에 주입해 mono 테마 HTML 생성. lens_policy.select_theme() 가 사건 카테고리에서 burgundy_mono / light_mono 자동 선택. 차트는 charts.js (inline payload 스캔), 지도는 maps.js (d3-geo + TopoJSON) 가 SVG 로 렌더. wrangler 로 Cloudflare Pages 배포.composed_report.watch_signals 를 SQLite Registry 에 INSERT. 텔레그램 /watchlist, /fire 명령으로 후속 추적.composer 가 ComposedSection.charts 의 각 dict 로 type 1개씩 emit. type 별 data 스키마는 composer SYSTEM_PROMPT 가 SSOT. charts.js 가 inline payload 스캔 후 mono guide §4 패턴으로 SVG 렌더.
| type | 용도 | data 스키마 | 게이팅 |
|---|---|---|---|
| donut | 비중 비교 | [{label, value:number, note?}] | ≥3개 + non-uniform |
| bar | 순위·분포 | [{label, value:number, note?}] | ≥1 |
| line | 시계열 추이 | [{x, y:number, event?}] | ≥2 점 |
| gantt | 사건 구간 | [{label, start, end, note?}] | ≥1 |
| network | 관계도 | {nodes:[{id,label,group?}], links:[{source,target,type?}]} | nodes ≥2 |
| stacked | 시나리오 × 행위자 영향 | {scenarios:[{name, segments:[{label,value}]}]} | ≥1 row |
| bubble | 확률 × 영향 매트릭스 | [{label, x:number, y:number, size?}] | ≥1 |
| heatmap | 단계별 위험도 | [{title, severity:'low'|'medium'|'high'}] | ≥1 |
색이 mono 한 hue 로 수렴하므로 카테고리 구분은 45° 패턴 + 액센트 솔리드. 핵심 항목은 accent solid, 그 외는 패턴 순환 (hatch-tight → accent-hatch → hatch-wide → dots).
v4.2.0 에서 maplibre-gl 의존 폐기 (mono guide §2). composer 가 ComposedReport.embedded_map 에 lat/lng + arcs 를 직접 emit, maps.js 가 d3.geoMercator + world-atlas/110m TopoJSON 으로 정적 SVG 렌더.
외부 타일 서비스 / 글리프 PBF 호출 / 스키마 변경에 취약. 샘플 페이지가 빈 배경으로 떨어지는 회귀 발생. 모바일 ISP 차단 / CDN 캐시 / Content-Type 문제로 신뢰할 수 없음. world-atlas 110m TopoJSON 한 번 fetch (~100KB) 로 전 세계 국경 벡터를 받아 정적 SVG 로 렌더 → 인쇄·캡처 모두 안정적.
호 색상은 highlight 여부로 accent / muted 분리. 1차 회랑 (highlight=true) 은 실선 굵게, 보조 항로는 점선 얇게. 마커는 highlight 만 accent + 굵게. 베이스맵은 mono 토큰 (--map-land / --map-water / --map-boundary) 으로 동적 적용.
composer 가 emit 하는 단일 출력 객체. v4.0.0 → v4.2.0 사이 추가된 필드는 + 표시.
취소선 = 코드 보존하되 호출 안 됨. 초록 = v4.x 신규 또는 강화. 추후 cleanup commit 시 deprecated 모듈 일괄 제거 예정.
v4.2.0 변경은 코드 + 모델 + 템플릿 + 정적 자산 4개 영역 모두 영향. VM 재기동 필수.
cd ~/agents_reviewer
git pull origin main
pkill -9 -f 'python -m src.main' # 옛 인스턴스 일괄 종료 (literal <PID> 입력 실수 회피)
sleep 2
source venv/bin/activate
nohup python -m src.main > bot.log 2>&1 &
disown
sleep 5 && tail -30 bot.log
확인: 텔레그램 /status → VERSION: v4.2.0 + 에이전트 구성 2명 (상황 분석관 / 편집장 모두 Opus 4.7) 표시. 분석 후 보고서 footer 에 archetype: freeform_essay 표시.