Event Analysis Team · System Architecture

v3.5.0 — Composer-First, Mono-Only

텔레그램 메시지 한 줄을 받아 다중 LLM 분석을 거친 뒤 자유 형식 mono 보고서를 생성하는 시스템. 보고서 형태는 사건마다 LLM 편집장이 자유 결정함.

v3.5.0 main · 733d604 Python 3.11+ · Pydantic v2 Cloudflare Pages · Oracle Cloud VM Mono Guide v3.4.7

한 화면 요약

입력: 텔레그램에 사건 한 줄 (예: "미국-이란 호르무즈 봉쇄 분석"). 심층/짧게/요약 같은 키워드로 분석 강도 모드 자동 결정.

처리: 1) 상황 분석관 이 웹 검색으로 사실·타임라인·출처 수집 → 2) 전략 기획자 가 핵심 질문/의도/렌즈 결정 → 3) 모드별로 페르소나·렌즈 1~4종이 다각도 분석 → 4) 종합 판단관 이 모순/판단 정리 → 5) 편집장 (Opus 4.7) 이 보고서 본문을 자유 형식으로 작성 → 6) HTML 렌더 후 Cloudflare Pages 배포.

출력: mono 톤 HTML 보고서 URL. 사건마다 섹션 수/제목/순서/톤이 다름 (정형 슬롯 부어넣기 폐기).

핵심 변화 v3.4.7 → v3.5.0: 편집장 이 모든 모드에서 호출됨. 차트는 편집장이 본문에서 명시 reference 한 것만 박힘 (이전엔 데이터만 있으면 9종 차트가 무차별 발화). 테마는 mono 2종 (burgundy_mono · light_mono) 만 사용.

3단 모드 정책

token_budget.py 가 SSOT. 사용자 메시지의 키워드로 자동 매핑되며 (없으면 standard), 호출되는 에이전트 / 렌즈 수 / LLM 호출 cap 이 다름.

항목fast ⚡standard 🟢deep 🔬
키워드짧게/간략/요약/빠르게(기본)심층/자세히/면밀
LLM 호출 cap5813
최대 lens 개수124
레거시 페르소나 (Player/Dynamics/ChainReaction)미호출미호출호출
Quality Gate 1 LLM휴리스틱만휴리스틱만LLM
Quality Gate 2 (커버리지)스킵휴리스틱LLM
Synthesis Judge LLM휴리스틱조건부LLM
red_team / pre_mortem 메타 lens없음조건부자동
NarrativeComposer (편집장 Opus 4.7)호출 (v3.5.0)호출 (v3.5.0)호출
v3.5.0 차이

이전 (v3.4.7) 에는 fast/standard 에서 편집장이 호출되지 않아 정형 archetype 11종 중 1개에 데이터를 슬롯-부어넣는 패턴이었음. 이제 모든 모드에서 편집장이 보고서 본문을 자유 작성하므로 보고서 형태가 사건마다 다름.

한 사건당 파이프라인

한 분석 1회당 거치는 단계. 점선 박스는 모드 또는 조건부 호출, 굵은 골드 좌측 보더는 편집장 (composer), 점선 좌측 도트는 결정적 (LLM 없음).

상황 분석관 — ContextAnalyst
Sonnet 4.6 · 웹 검색 활성 · 모든 모드 호출
사건의 사실 / 타임라인 / 핵심 수치 / 출처 URL 을 수집. 1차 사실 검증 단계로 후속 모든 단계의 입력 근거가 됨. 출처를 ContextAnalysis.sources 로 보존.
전략 기획자 — Strategy Planner
Opus 4.6 · 모든 모드 호출 · 단일 LLM 호출
상황을 보고 event_type / user_intent / core_questions 를 결정. v3.1.0 부터 lens 선택과 theme 선택은 LLM 이 아닌 코드 정책 (lens_policy.py) 이 처리.
Quality Gate 1 — 계획 sanity check
Sonnet 4.6 · deep 만 LLM, 그 외 휴리스틱
전략의 의도-렌즈 정합성 확인. 실패 시 전략 재생성 1회 시도.
레거시 페르소나 3종 (deep 만)
Sonnet 4.6 + Opus 4.6 + Sonnet 4.6 · 순차 호출
이해관계 분석관 (PlayerAnalyst, Sonnet) → 핵심 행위자 식별, 입장·전략·취약점.
구조 분석관 (DynamicsAnalyst, Opus) → 구조적 원인, 비대칭, 피드백 루프, 전환점.
연쇄반응 분석관 (ChainReactionAnalyst, Sonnet) → 인과 사슬, 차단 가능 지점, 와일드카드.
fast/standard 에서는 lens pool 의 stakeholder/structural/cascade lens 가 대체.
시나리오 설계관 — ScenarioArchitect
Opus 4.6 · 모든 모드 호출
3~5개 시나리오 설계 + 감시 신호 + 무효화 조건. fast 에서도 호출됨 (보고서의 핵심 가치).
Lens Pool — 1~4 lens 분석
코드 정책 매핑 + 각 lens 별 LLM 호출
사건 카테고리에 맞춰 lens_policy.py 가 결정한 1~4종 렌즈 (geopolitical / financial_transmission / tech_architecture / accident_causality / market_structure / stakeholder / structural / cascade / red_team / pre_mortem 등) 가 각자 finding 을 emit. 각 finding 은 claim + evidence_id 1+ 강제.
종합 판단관 — SynthesisJudge
Opus 4.6 · deep 만 LLM, 그 외 휴리스틱
finding 들의 모순 표면화 (Anti-pattern #5: 봉합 금지). 패배한 입장은 counter_hypothesis 로 보존. 신뢰도 3축 분해 (출처 다양성·신선도·전문가 합의) 산출.
Quality Gate 2 — 커버리지 확인
Sonnet 4.6 · deep 만 LLM
core_questions 가 finding 으로 답변됐는지 확인. 미답변 시 judgment 재생성 1회.
편집장 — NarrativeComposer ⭐
Opus 4.7 · 모든 모드 호출 (v3.5.0) · 단일 LLM 호출 (max 8K 토큰)
7개 분석가의 finding/claim/judgment 를 모두 받아서 보고서 본문을 자유 형식으로 작성. 섹션 수 (3~7개) / 제목 / 순서 / 톤 / pull quote / 차트 referencing 모두 LLM 결정. 각 주장은 cited_claim_ids 로 evidence 추적성 강제. 차트는 embedded_charts: [chart-id] 에 적은 것만 본문에 박힘. 실패 시 archetype 폴백.
시각화 빌더 — visual_builder
코드 결정적 · LLM 호출 0
9종 d3 차트 데이터 (시나리오 막대 / 핵심 수치 도넛 / 인과 사슬 히트맵 / 신뢰도 3축 / 시계열 / 누적막대 / 리스크 매트릭스 / 간트 / 행위자 네트워크) 를 분석 결과에서 자동 추출. v3.5.0 핵심: 추출만 하고 자동 박지 않음. 편집장이 명시 reference 한 chart-id 만 freeform_essay.html 이 렌더.
보고서 합성 — ReportSynthesizer
Sonnet 4.6 (executive summary 만, 옵션) · 결정적 HTML 렌더
composer 의 ComposedReport 또는 (실패 시) archetype 의 section_plan 을 받아 mono 테마 HTML 생성. freeform_essay.html 또는 report_block.html 폴백. wrangler 로 Cloudflare Pages 에 배포 후 URL 반환.
Watchlist 등록
SQLite · LLM 없음
시나리오의 watch_signals 를 SQLite 레지스트리에 INSERT. 텔레그램 /watchlist, /fire 명령으로 후속 추적.
호출 수 합산

fast 5회 (context + strategy + scenarios + lens 1 + composer) · standard 8회 · deep 13회. Quick mode 진입 시 모든 에이전트가 Sonnet 4.6 으로 다운그레이드.

에이전트 카탈로그

현재 v3.5.0 에서 살아있는 7개 에이전트. 좌측 보더 굵은 솔리드 = Opus 라인 (heavy). 점선 사선 패턴 = Sonnet 라인 (light). 골드 글로우 = 편집장 (Opus 4.7).

상황 분석관
ContextAnalyst
claude-sonnet-4-6

웹 검색으로 사건의 사실/타임라인/핵심 수치/출처 URL 수집. 1차 evidence 의 출처가 됨.

all modes
시나리오 설계관
ScenarioArchitect
claude-opus-4-6

3~5개 시나리오 (기본/최선/최악/구조전환) + 감시 신호 + 무효화 조건. confidence + driver_signals 도 emit.

all modes
이해관계 분석관 (deep)
PlayerAnalyst · 페르소나 (legacy)
claude-sonnet-4-6

핵심 행위자 식별, 입장·자원·전략·취약점·관계 구도. fast/standard 에서는 stakeholder lens 가 대체.

deep only
구조 분석관 (deep)
DynamicsAnalyst · 페르소나 (legacy)
claude-opus-4-6

구조적 원인, 비대칭, 피드백 루프, 전환점, 인지 편향, 반대가설. fast/standard 에서는 structural lens 가 대체.

deep only
연쇄반응 분석관 (deep)
ChainReactionAnalyst · 페르소나 (legacy)
claude-sonnet-4-6

인과 사슬 (단계별 severity / time_horizon / 가역성), 차단 지점, 와일드카드, 최악의 경우. fast/standard 에서는 cascade lens 가 대체.

deep only
종합 판단관
SynthesisJudge
claude-opus-4-6

모든 finding 의 모순 표면화 (봉합 금지). 신뢰도 3축 분해. core_question 미답변 자동 감지.

deep LLM · 그 외 휴리스틱
편집장 ⭐
NarrativeComposer
claude-opus-4-7

7명의 분석가 결과를 받아 보고서 본문을 자유 형식으로 작성. 섹션 수/제목/순서/톤/pull quote/차트 referencing 모두 결정. claim 인용 강제로 evidence 추적성 보존.

v3.5.0: all modes
품질 검사관
QualityInspector
claude-sonnet-4-6

Gate 1 (계획 sanity) + Gate 2 (커버리지). deep 에서만 LLM, 그 외 휴리스틱. 실패 시 1회 재시도.

deep LLM · 그 외 휴리스틱
VisualAnalyst (옛 시각화 분석관)

v3.0~v3.4.x 에 있던 시각화 LLM. v3.5.0 에서 모든 모드의 LLM 경로가 사실상 비활성. visual_builder.py 의 결정적 빌더가 9종 차트 데이터를 추출하지만, 자동 박힘은 차단됨. 편집장이 명시 reference 한 차트만 본문에 박힘.

렌즈 풀 (Lens Pool)

사건 카테고리 × 의도 × 모드 → lens_policy.select_lenses() 가 결정. 한 사건당 1~4종 (mode 별 cap). 각 렌즈는 독립 LLM 호출로 finding 을 emit.

lens_id적용 분야핵심 기법
geopolitical전쟁·외교·안보DIME / PMESII / Escalation Ladder / Capability-Intent
financial_transmission금융·거시Balance Sheet / Flow of Funds / Transmission Channel / Liquidity Stress
tech_architecture기술·AI·ITArchitecture Decomposition / Dependency Graph / Bottleneck
accident_causality사고·재난Fault Tree / Bow-Tie / Swiss Cheese / STAMP
policy_implementation정책·규제Stakeholder Incentive / Distributional Impact / Implementation Gap
market_structure시장·산업Network Analysis / Game Theory / Regime Shift
stakeholder행위자 분석 (페르소나 대체)이해관계자 식별·전략 매핑 — fast/standard 에서 PlayerAnalyst 대체
structural구조 분석 (페르소나 대체)피드백 루프·전환점 — fast/standard 에서 DynamicsAnalyst 대체
cascade인과 사슬 (페르소나 대체)전이 경로·차단점 — fast/standard 에서 ChainReactionAnalyst 대체
red_team메타 (반론)ACH / Devil's Advocate — what_to_do, where_vulnerable 의도
pre_mortem메타 (실패 시뮬)실패 가정 후 역설계 — what_next, where_vulnerable 의도

테마 시스템 — Mono Only

v3.5.0 에서 멀티컬러 6테마 (burgundy/geopolitical/financial/tech/nature/liquidglass) 를 통째 폐기하고 mono 2종만 사용. 카테고리 구분은 hue 가 아니라 패턴 (45° hatch) 과 명암으로. lens_policy.select_theme() 이 사건 카테고리에서 자동 선택.

Burgundy Mono (기본)

딥와인 + 앰버 골드 + 파치먼트. 정보 밀도 높은 분석에 적합. 일반·금융·기술·지정학·산업·사고 사건의 기본 테마.

Light Mono

크림 + 딥버건디 + 포레스트 그린. 편집·인쇄·문서 친화. 정책 사건 (policy_implementation) 의 기본 테마.

패턴 시스템 (mono guide §4)

색이 한 hue 로 수렴하므로 카테고리 구분은 4종 패턴 + 액센트 솔리드로. 모든 사선은 45° 한 방향만 (Anti-pattern: cross-hatch / opposite diagonals 금지).

hatch-tight
hatch-wide
accent-hatch
dots
accent solid

차트 시스템 — Composer-Referenced Only

visual_builder.build_chart_payload() 가 분석 결과에서 9종 차트 데이터를 결정적으로 추출. 그러나 자동 박지 않음. 편집장이 본문에서 명시 reference 한 chart-id 만 freeform_essay.html 에서 렌더 (mono guide anti-pattern #6: 무지성 차트 박힘 차단).

chart-id형식데이터 출처Insight Gate
chart-scenarios막대scenarios[].probability≥1
chart-figures도넛context.key_figures≥3 + non-uniform
chart-severity히트맵chain_reaction.chain[].severity≥1
chart-confidence3축judgment.confidence (3축)판단 존재
chart-stacked누적 막대scenarios[].impact_by_player≥4 segments + non-uniform
chart-bubble버블chain.wildcards (확률 × 영향)≥1
chart-gantt간트context.timeline≥2
chart-network포스players.players + alliances≥2 nodes
chart-timeseries(예약 — 미사용)
v3.5.0 의 차트 게이팅 흐름

① 분석 끝 → ② build_chart_payload() 가 가용 차트 데이터 추출 → ③ build_chart_catalog() 가 편집장에게 "지금 가용한 차트 목록" 전달 → ④ 편집장이 본문 작성 시 embedded_charts: ["chart-id"] 로 명시 → ⑤ 그 chart-id 만 freeform_essay.html 의 차트 카드로 렌더. 편집장이 reference 안 한 차트는 박히지 않음.

v3.5.0 = Option C — 무엇이 바뀌었나

v3.4.7 → v3.5.0 의 단일 PR. 보고서 자유도 확보 + mono 표준 적용 + 차트 무지성 박힘 차단.

미적용 (Tier 4 옵션)

다중 에이전트 + 렌즈 파이프라인을 1~2개로 압축해 분석 깊이를 trade-off 하는 변경은 v3.5.0 에서 진행하지 않음. 이해관계 분석관 / 구조 분석관 / 종합 판단관 등 7개 에이전트 모두 살아있음. v3.5.0 의 자유도 결과를 며칠 운용해본 뒤 깊이가 충분한지 확인하고 결정할 사안.

키 파일 맵

v3.5.0 의 핵심 파일. 골드 = 디렉토리, 진한 텍스트 = SSOT 위치.

src/ ├── orchestrator.py ← 4-Phase 파이프라인 진입점, VERSION 상수 ├── models.py ← Pydantic SSOT (AnalysisStrategy, FullAnalysisResult, ComposedReport) ├── token_budget.py ← mode (fast/standard/deep) 별 정책 SSOT ├── lens_policy.py ← (event_type, intent, mode) → lens / theme 결정 ├── visual_builder.py ← 9종 d3 차트 데이터 결정적 빌더 (LLM 0) ├── telemetry.py ← 사건당 LLM 호출 / 단계별 elapsed 기록 ├── brief_builder.py ← FullAnalysisResult → 압축 brief ├── agents/ │ ├── context_analyst.py ← Sonnet 4.6 (웹검색) │ ├── player_analyst.py ← Sonnet 4.6 (deep 페르소나) │ ├── dynamics_analyst.py ← Opus 4.6 (deep 페르소나) │ ├── chain_reaction_analyst.py ← Sonnet 4.6 (deep 페르소나) │ ├── scenario_architect.py ← Opus 4.6 │ ├── synthesis_judge.py ← Opus 4.6 (모순 표면화) │ ├── quality_inspector.py ← Sonnet 4.6 (Gate 1, 2) │ ├── narrative_composer.py ← Opus 4.7 ⭐ 편집장 │ ├── report_synthesizer.py ← HTML 렌더 + Cloudflare 배포 │ └── visual_analyst.py ← LLM 시각화 (사실상 비활성) ├── lenses/ ← 11종 렌즈 ├── archetypes/ ← 11종 아키타입 (composer 실패 시 폴백) │ └── freeform_essay.py ← 편집장 출력 전용 SSOT ├── templates/ │ ├── report.css ← Mono 2테마 SSOT (burgundy_mono + light_mono) │ ├── report.html ← (legacy 페르소나 풍부 데이터 → 6막 극장) │ ├── report_block.html ← 블록 시스템 폴백 (차트 9슬롯 삭제됨) │ ├── archetypes/ │ │ ├── freeform_essay.html ← ⭐ 편집장 출력 렌더 (디폴트 경로) │ │ ├── financial_transmission.html │ │ └── tech_decomposition.html │ ├── blocks/ ← 17종 블록 템플릿 (timeline / actor_cards / scenario_table 등) │ └── static/ ← d3 / charts.js / charts.css / maps.js ├── tests/ ├── telegram_bot.py ← 봇 진입점 (textfile) ├── watchlist/ ← SQLite registry └── main.py ← python -m src.main 진입점 docs/ ├── MONO_THEME_GUIDE.md ← 본 페이지의 SSOT (Tier 2) ├── ARCHITECTURE.md ├── REPO_MAP.md ├── CATALOGS.md └── DATA_MODELS.md samples/ ├── chart_map_mono_compare.html ← mono 비교 샘플 └── v3_5_0_architecture.html본 페이지

운영 — 봇 재기동

코드 변경 시 VM 의 봇 프로세스 재기동 필요. orchestrator 가 프로세스 시작 시점에 BUILD_INFO (branch / commit / VERSION) 를 캡처해 텔레그램 /status 응답에 노출.

재기동 절차

cd ~/agents_reviewer
git pull origin main
kill -9 <old_pid>
source venv/bin/activate
nohup python -m src.main > bot.log 2>&1 &
disown

확인: 텔레그램 /statuscommit: 733d604 / VERSION: v3.5.0 출력. 옛 commit 이 보이면 재기동 안 된 것.