Sub-skill: Quality Control (Wagschal + Pitfall)
출처: Glenn (2009) V3.0 06장 §IV "Strengths and Weaknesses" + §III.A "rule of unanimity" + endnote 4 (correlation/causation philosophy) 상위 마스터:
vision-foresight-futures-wheel호출 권한: 마스터 orchestration 전용 (disable-model-invocation: true)
1. PDF 원전 정의
1.1 Wagschal Unanimity Rule (§III.A)
"Alternatively, the impacts of an event or trend can be processed more slowly and deliberately by accepting criticism prior to entering anything on the wheel. In this approach, the group discusses the plausibility of every impact. If an impact is judged plausible by all, then it is entered; otherwise, not. Peter Wagschal refers to this as the 'rule of unanimity.' He argues that making sure everyone agrees is one way of ensuring that the impacts are reasonable: 'The Futures Wheel process leads rapidly to unexpected consequences and, thus, requires a restriction on the group to prevent them from arriving at conclusions that are so speculative as to be of little worth in assessing alternative futures.'"
1.2 Intellectual Spaghetti (§IV)
"If one is not disciplined in using the Futures Wheel, one can end up with some messy 'intellectual spaghetti' that makes the implications of the trend or event more difficult to see clearly. The use of primary, secondary, etc. rings is one way to help prevent the problem; another is the use of the single, double, triple, etc., lines to organize the linkages among the impacts as in Figure 4."
1.3 Premature Judgment + Butterfly Effect (§IV)
"One mistake is to see the possible impacts or consequences as truly representing what will happen. One might be tempted into believing that a single triggering fact is sufficient to generate an avalanche of impacts. Although such events do occur (such as attractors in chaos theory, which give rise to 'butterfly effects' — how a seemingly insignificant event like a butterfly passing by can catch one's attention, changing the previously expected flow of events) the Futures Wheel can help to identify them. However, one must guard against making dangerously premature judgments."
1.4 Correlation vs Causation (endnote 4)
"Philosophically, one cannot claim certainty of causality. One situation may appear to be caused by another situation, when in fact they may both be caused by a third situation not visible to the observer. This point in a futures context is well explained by Bertrand de Jouvenel in The Art of Conjecture. The philosopher David Hume in On Human Nature demonstrated that what we call causality is a habit of the mind formed by seeing one thing vary with another. It is the variation and correlation that we can know, but not the truth of causality. Impacts and consequences imply causality. Originally, one would do a Futures Wheel by answering the question, 'What are the necessary correlations (not in the mathematical sense) with the event or trend?' However, since the method is designed to help thinking rather than determine truth (since 'truth' does not apply to the future anyway), the normal use of the method today asks what are the likely impacts or consequences, as if we can really ascertain the causal relations. This paper reflects how the method is used in common practice and, hence, will only refer to impacts and consequences rather than correlations."
1.5 Method Weaknesses (§IV)
"Weaknesses. Like Simulation Games, Delphis, or Syncons, the Futures Wheel is no better than the collective judgments of those involved. It can make a group or individual think they understand causal relations between the items that emerge, when it is possible that they have only identified correlations. The Futures Wheel can be too simplistic at times, blurring the distinctions on the timing of one identified impact relative to other impacts and the probability of one consequence relative to others."
1.6 Method as Input, Not Truth (§IV)
"The output of a Futures Wheel should be used as a basis for further thinking, for more systematic exploration, and for the application of other techniques for probing the future. Put simply, the Futures Wheel is a creative tool that generates input to futures thinking."
2. AI Agent 11인 구성 + Final Gate Keeper
| Agent | 역할 | Gate |
|---|---|---|
| Wagschal Critic | 각 impact의 panel 만장일치 plausibility 점검 | Gate 1 |
| Spaghetti Auditor | 시각화 명료성, ring/line 구조화 점검; visual_clarity_score 결정론 계산 (§10.1) | Gate 2 |
| Premature Judgment Guard | avalanche 효과 의심, 단일 trigger의 단정 회피 | Gate 3 |
| Causation Sleuth | 인과·상관 명시적 구별, 제3 변수 의심 | Gate 4 |
| Butterfly Detector | chaos theory attractor·"butterfly effect" 식별 | Gate 5 |
| Timing Auditor | 차수별 시간 간극 일관성, blur 점검 | Gate 6 |
| Probability Auditor | impact 별 확률 비교 명시 점검 | Gate 7 |
| Strengths Self-Auditor | Glenn §IV 5 strengths 자가 검증 (extension 1건 별도 표시) | Gate 8 |
| Citation Validator | 모든 impact inline citation 100% 검증, vague attribution 0, fabricated source 0 | Gate 9 |
| Reasoning Chain & SRS Auditor | CoER 3-step chain 검증 + Python SRS 계산 (§10.2) + MDE compliance | Gate 10 |
| SCBE Compliance Auditor ⭐ | Cycle 9 전용 (비-C9 자동 SKIP): 균일 2-fan-out·카테고리 균형·총 노드수·3LDP 검증 (§10.3) | Gate 11 |
| Final Gate Keeper | 11 Gate 통합 PASS/REVISIONS_REQUIRED/FAIL 판정; quality_score 결정론 계산 (§10.4) | All |
3. 11 Audit Gate 처리 흐름
Gate 1 — Wagschal Unanimity Rule
각 impact에 대해:
wagschal_audit:
impact_id: P1
text: "AGI로 화이트칼라 자동화 50% 진행"
panel_vote_simulation:
Glenn: plausible (5 panelists 가상)
Bishop: plausible
Coates: plausible
Snyder: speculative (concerns about timeline)
Voros: plausible
unanimity: false # Snyder가 speculative 표
action:
option_A: refine wording until unanimity
option_B: mark with [low-unanimity] flag and lower visibility
option_C: drop from wheel
recommendation: option_A
refined_text: "AGI로 화이트칼라 *부분* 자동화 가속 (속도 불확실)"
re_vote: 5/5 plausible
만장일치 미달 시 3가지 옵션 자동 적용:
- A. Refine: 워딩 다듬어 재투표 (가장 일반적)
- B. Flag: low-unanimity tag로 보존, oval 작게 표시
- C. Drop: 너무 speculative하면 제거
Gate 2 — Intellectual Spaghetti Audit
visual_clarity_score 결정론 계산 공식 — LLM 재추론 금지; §10.1 calculate_visual_clarity_score() 호출:
| 감점 항목 | 감점 크기 |
|---|---|
| ring 경계 미구별 (per violation) | −0.15 |
| single/double/triple 선 미구별 | −0.10 |
| domain 버킷 미표시 (per unlabeled) | −0.10 |
| cross-linkage 미표시 (per edge) | −0.03 |
| feedback loop 미강조 (per loop) | −0.05 |
| 최저 보장 | 0.0 (음수 방지) |
- spaghetti_risk 분류:
low≥ 0.75 /medium0.50–0.74 /high< 0.50
spaghetti_audit:
total_nodes: 32
total_edges: 41
graph_density: 0.041
visual_clarity_score: <§10.1 결정론 계산값> # LLM이 직접 수치 생성 금지
structure_checks:
- rings_clearly_distinguished: ✓
- line_types_distinguished: ✓ (single/double/triple)
- domain_buckets_labeled: ✓ (V2 활용 시)
- cross_linkages_explicitly_marked: ✓
- feedback_loops_separately_highlighted: ✓
spaghetti_risk: low|medium|high # 위 기준으로 결정론 분류
if_high:
recommended_actions:
- "사용 ring 줄이기 (3차 → 2차)"
- "cross-linkage를 별도 diagram으로 분리"
- "도메인 그룹화 강화"
- "차수별 표로 분할"
Gate 3 — Premature Judgment Guard
결정론 범위 명시: Gate 3은 가정 의존성 식별과 qualitative alert 생성이 본질이므로 LLM 추론이 불가피하다. 단, alert 구조 포맷은 아래 YAML을 엄수하여 hallucination을 최소화. 수치·확률 클레임이 포함된 경우에만 Gate 9·10의 결정론 체크와 연동.
각 high-confidence impact에 대해:
premature_guard:
impact_id: P1
confidence_level: 5/5 # 가장 높은 신뢰
audit_questions:
- "이 impact이 단일 triggering fact에 기반하는가?"
- "다른 attenuating factor가 누락되지 않았는가?"
- "역사적 analog가 실제로 같은 path를 따랐는가?"
- "panel의 confidence가 *어떤 가정*에 기반하는지 명시되었는가?"
alerts:
- "P1은 단일 가정(AGI 2028 출현)에 강하게 의존. 가정 변경 시 hooked chain 전체 흔들림"
required_disclosure:
- "이 분석은 {가정 1, 가정 2}가 성립할 때만 유효"
- "Confidence는 *판단*이지 *예측*이 아니다"
Gate 4 — Correlation vs Causation Guard
causation_audit:
edges_total: 41
edge_classification:
direct_causation: 18 # A가 명백히 B를 일으킴
necessary_correlation: 15 # A 없이 B 없음 — 인과 의심 가능
contingent_correlation: 6 # A와 B가 같이 보이지만 제3 변수 의심
unclassified: 2
third_variable_alerts:
- edge: P1 → S1a
issue: "P1(자동화)와 S1a(임금 하락)는 모두 P0(자본 집중)에서 비롯될 가능성"
action: "edge label에 [contingent] flag"
- edge: P2 → S2a
issue: "P2(데이터센터 수요)와 S2a(SMR 부상)는 같은 P-X(에너지 전환 정책)의 두 결과일 수 있음"
action: "추가 edge 'P-X → P2, P-X → S2a' 검토"
philosophical_disclosure_required: true
disclosure_text: |
"본 wheel의 edge는 인과(causation)가 아닌 *likely impacts*를 표시한다.
Hume·de Jouvenel 철학에 따라 인과 자체는 입증 불가하며, 우리는
correlation을 관찰할 뿐이다. 따라서 각 edge는 '~할 가능성이 있다'로 해석."
Gate 5 — Butterfly Effect Awareness
butterfly_audit:
small_events_overlooked: [] # Brainstorm panel이 무시한 작은 사건
attractor_candidates:
- event: "한국 출산율 0.5 진입"
potential_amplification: "임계점 통과 후 사회 시스템 재조직 trigger 가능"
panel_attention: low # 작아 보여서 주목 못 받았음
- event: "특정 GPU export 규제 강화"
potential_amplification: "글로벌 AI 산업 지정학 재편 가속 가능"
panel_attention: medium
recommended_addition:
- "wheel에 'attractor' 표시 영역 추가 — 작지만 amplification 가능 후보"
- "각 attractor 후보를 별도 시나리오 분기점으로 promote"
Gate 6 — Timing Distinction Audit
timing_audit:
primary_ring_time_range:
expected: T+1~5y
actual_spread: T+0.5y ~ T+6y
consistency: good
secondary_ring_time_range:
expected: T+5~10y
actual_spread: T+3y ~ T+12y
consistency: blurred # ⚠️
blur_examples:
- S1a: T+3y (너무 빠름 — primary와 겹침)
- S3c: T+12y (너무 늦음 — tertiary 영역)
recommended_action: "S1a는 primary로 재분류, S3c는 tertiary로 재분류"
tertiary_ring_time_range:
expected: T+10~20y
actual_spread: T+10y ~ T+25y
consistency: acceptable
Gate 7 — Probability Comparison Audit
probability_audit:
probability_assigned: 18/32 nodes # ⚠️ 모든 노드에 미할당
unassigned_nodes: 14
required_action: "각 impact에 *상대* 확률 등급 부여 (very high / high / medium / low / very low)"
cross_node_comparison:
higher_probability: [P1, P2, P3]
medium: [P4, S1a, S2a, S1b]
lower: [P5, S3c, T1a1]
visualization_directive:
- line_thickness ∝ probability
- dotted line for low-probability edges
Gate 8 — Strengths Self-Affirmation
Glenn §IV Strengths 5종 자가 점검 (출처: Glenn 2009, V3.0 06장 §IV):
strengths_self_audit:
# --- Glenn §IV 5 core strengths ---
- strength: "Easy and enjoyable — gets people thinking quickly"
source: "Glenn (2009) §IV Strengths"
check: AI Agent panel이 빠르게 활성화됨
- strength: "Identify positive and negative feedback loops"
source: "Glenn (2009) §IV Strengths"
check: consequence-linker가 FL-1, FL-2 식별
- strength: "Move from linear/hierarchical to network thinking"
source: "Glenn (2009) §IV Strengths"
check: cross-linkage 6 발견 — network thinking 작동
- strength: "Visual map of complexity"
source: "Glenn (2009) §IV Strengths"
check: Mermaid + ASCII + table 3종 산출
- strength: "Reveal contradictions as critical issues"
source: "Glenn (2009) §IV Strengths"
check: 2 contradiction을 critical issue로 promote
# --- Extension (Glenn §IV 직접 인용 아님; 방법론 문헌 일반 확장) ---
- strength: "Tie into formal systems model"
source: "Extension — not a direct Glenn §IV citation"
extension: true
check: Causal Loop Diagram export 가능
all_glenn_strengths_demonstrated: true # 5 core Glenn §IV strengths
extension_demonstrated: true # 1 extension (별도 표시)
final_gate: PASSED
Gate 9 — Citation Completeness ⭐ (박사님 2026-05-11 강화 명령 #3)
citation_audit:
total_impacts: N
per_impact_checks:
inline_citation_present:
target: 100% # 예외 없음 — 95% 이하 모두 FAIL
current: <%>
citation_format_valid:
acceptable:
- "[저자/기관, 연도]" # 비웹 출처 최소 형식
- "[저자, 연도, URL]"
- "[저자, 연도, 제목, URL, page]" # 최상위 형식
reject: ["(전문가 의견)", "(연구에 따르면)", "(보고서)"]
quantitative_claim_R1_sourced:
check: "specific number/percentage/date에 R-1 출처 있는가"
target: 100%
fabricated_source_check:
patterns:
- '"study by .* University" (URL 검증 없으면)'
- '"research from .* Institute" (URL 검증 없으면)'
- '"according to .* paper" (URL 없으면)'
reject_action: 자동 삭제 + flag
fail_condition:
# strictness에 따라 임계치 분기 (§7 strictness 참조)
wagschal_or_default:
- citation_present_rate < 100%
- vague_attribution_count > 0
- fabricated_source_count > 0
balanced:
- citation_present_rate < 95% # 완화 임계치
- vague_attribution_count > 0
- fabricated_source_count > 0 # citation_rate=100%여도 독립적으로 FAIL
fast:
- gate_9_skipped: true # fast 모드에서 Gate 9 비활성
# NOTE: fabricated_source_count > 0 조건은 citation_present_rate와 독립.
# 모든 impact에 citation이 있어도 fabricated source 1건이면 FAIL.
on_fail: REVISIONS_REQUIRED → deep-reasoning-engine 재호출
Gate 10 — Reasoning Chain Validity + SRS ⭐ (박사님 2026-05-11 강화 명령 #1·#2)
CoER (Chain of Evidence Reasoning): 각 impact에 대해 "근거 사실(R-1) → 중간 추론(R-2) → 도출 주장(H)" 3단계로 추론 경로를 명시. LLM 자연어 재추론이 아닌 출처 체인으로 할루시네이션을 구조적으로 차단.
SRS (Sewongjima Reversal Score): 박사님 proprietary metric (세옹지마·塞翁之馬 고사에서 명명; 표준 학술 용어 아님). 각 lineage에서 consecutive sign reversal 횟수를 계산하여 "wheel이 단순 직선 증폭이 아닌 반전·순환을 충분히 반영하는가"를 측정.
SRS Sign Notation (전 게이트 공통):
🟢= positive impact (긍정적 결과)🔴= negative impact (부정적 결과)🟡= neutral/ambiguous (중립·양가; reversal count 제외)- Reversal = 연속된
🟢→🔴또는🔴→🟢전환
[결정론 위임] SRS 계산 및 forced reversal 검사는 §10.2 Python 함수 calculate_srs() / check_forced_reversals() 호출. LLM이 직접 sign reversal을 카운트하지 않는다.
reasoning_chain_audit:
for_each_impact:
chain_length: ≥3 steps required
step_1_R1_present:
check: "base fact에 R-1 출처 있는가"
step_2_R2_present:
check: "intermediate inference에 R-2 출처 또는 analog 있는가"
step_3_disclosure:
check: "leap step에 H tag + 가정 disclosure 있는가"
fail_condition:
- any impact with chain_length < 3
- any step without R-tag
- any leap step without H-tag disclosure
SRS_audit:
# [결정론] §10.2 calculate_srs(sign_sequences) 호출 필수 — LLM 직접 계산 금지
lineage_format: "Center→Primary→Secondary→Tertiary→Quaternary→Quinary→Senary"
sign_sequences: [<각 lineage의 sign 리스트>]
per_lineage_minimum: ≥1 reversal
global_avg_target: ≥1.5
forced_reversal_checks:
# [결정론] §10.2 check_forced_reversals(sign_sequences, depth=6) 호출
T_to_Q (1차 강제 반전 — Tertiary→Quaternary):
rule: "≥50% lineages에서 Quaternary sign이 Tertiary와 반대"
Q_to_Qn (2차 강제 반전 — Quaternary→Quinary):
rule: "≥50% lineages에서 Quinary sign이 Quaternary와 반대"
Qn_to_Sn (3차 강제 반전 — Quinary→Senary):
rule: "≥50% lineages에서 Senary sign이 Quinary와 반대"
srs_gate_outcome_mapping:
PASS: "global_avg ≥ 1.5 AND all forced_reversal_checks PASS"
PARTIAL: "1.0 ≤ global_avg < 1.5 AND no forced_reversal FAIL → Gate 10 = PARTIAL"
REJECT: "global_avg < 1.0 OR any forced_reversal_check FAIL → Gate 10 = FAIL"
fail_condition:
- global_avg < 1.0 → 직선적 단정 → REJECT (Gate 10 FAIL)
- any forced_reversal_check 미달 → 세옹지마 효과 미달성 → REJECT (Gate 10 FAIL)
# PARTIAL zone (1.0 ≤ avg < 1.5): Gate 10 status = PARTIAL; quality_score에서 0.5 × 0.12 반영
MDE_compliance (Minimum Depth Enforcement):
depth_target: 6
exceptions:
- condition: "사용자가 '간단히'/'빠르게'/'대충' 명시"
min_depth_allowed: 3
- condition: "마스터가 명시적으로 중간 깊이 지정"
min_depth_allowed: 4 or 5 (마스터 지정값 따름)
fail_condition:
- depth_reached < 6 (예외 없이) → REVISIONS_REQUIRED
on_fail:
action: REVISIONS_REQUIRED
caller_directive: "basic-v1 Phase 6·7·8 진행 + deep-reasoning-engine Gate_P4·P5·P6_Pre 재호출"
Gate 11 — SCBE Compliance ⭐ (박사님 2026-05-11 2차 강화)
활성화 조건: Cycle 9 (C9) SCBE 모드 전용. 비-C9 동작: 자동 SKIP → gates_passed에 11 추가 (감점 없음; quality_score 에서 SKIP = 1.0 처리).
[결정론 위임] 총 노드 수 계산 및 fan-out 검증은 §10.3 Python 함수 validate_node_count() / check_fanout_uniformity() 호출.
SCBE_compliance_audit:
activation_condition: "cycle == 'C9'"
on_skip_condition: "cycle != 'C9'"
on_skip_action: "Gate 11 → auto-PASS (SKIP); gates_passed += [11]; gates_skipped += [11]"
uniform_fanout_check:
rule: "Senary leaf를 제외한 모든 노드는 정확히 2 children"
target: 100%
measurement:
# §10.3 check_fanout_uniformity(tree) 호출
total_non_leaf_nodes: N
nodes_with_exactly_2_children: M
compliance_rate: M / N
fail_threshold: <100%
category_balance_check:
rule: "각 ring에서 STEEPS 카테고리별 노드 수 ±0 균등"
expected_per_ring (STEEPS 6 frame):
Primary: 1 per category (총 6)
Secondary: 2 per category (총 12)
Tertiary: 4 per category (총 24)
Quaternary: 8 per category (총 48)
Quinary: 16 per category (총 96)
Senary: 32 per category (총 192)
measurement:
per_ring_variance: σ_max - σ_min
target: 0 (perfect balance)
total_node_count_check:
# §10.3 validate_node_count("STEEPS",6,2) → expected 379
# 검산: 1 + 6 + 12 + 24 + 48 + 96 + 192 = 379
STEEPS_6_expected: 379
# §10.3 validate_node_count("V2",6,2) → expected 505
# 검산: 1 + 8 + 16 + 32 + 64 + 128 + 256 = 505
V2_8_expected: 505
tolerance: ±0
anchored_tagged_model_check:
rule_1: "모든 노드에 primary_tag 존재 (STEEPS 카테고리 중 하나)"
rule_2: "secondary_tags는 옵션, 0~3개 허용"
rule_3: "자손은 부모의 primary_tag 기본 계승; deviation은 명시적 disclosure 필수"
measurement:
nodes_with_primary_tag: <%>
inheritance_compliance: <%>
3LDP_output_check:
layer_1_present: "Executive Summary (≤1 page) 생성"
layer_2_present: "Categorical Tree (collapsible mermaid) 6 또는 8 카테고리 모두"
layer_3_present: "Full Node Catalog (모든 379 또는 505 노드)"
fail_conditions:
- uniform_fanout < 100%
- category_balance variance > 0
- total_node_count != expected
- primary_tag 누락 노드 존재
- layer 1/2/3 누락
on_fail: REVISIONS_REQUIRED → categorical-binary-expansion 재호출
4. 18 Pitfall Checklist (Glenn §IV + endnotes 종합)
| # | Pitfall | Audit Gate |
|---|---|---|
| 1 | Treating impacts as actual predictions | Gate 3 |
| 2 | Single-fact avalanche assumption | Gate 3 |
| 3 | Correlation/causation confusion | Gate 4 |
| 4 | Intellectual spaghetti (over-complex) | Gate 2 |
| 5 | Missed feedback loops | Gate 8 (strengths) |
| 6 | Time blurring between rings | Gate 6 |
| 7 | No probability comparison | Gate 7 |
| 8 | Speculative impacts entered without unanimity | Gate 1 |
| 9 | One-domain dominance (bias) | (delegated to domain-v2 audit) |
| 10 | Cross-linkage missed | (delegated to consequence-linker) |
| 11 | Contradictions overlooked rather than promoted | (delegated to consequence-linker) |
| 12 | Butterfly/attractor candidates ignored | Gate 5 |
| 13 | Output mistaken as truth (not "creative tool") | Gate 3 |
| 14 | Premature judgment from confident-looking ring | Gate 3 |
| 15 | No follow-up systematic exploration plan | Gate 8 |
| 16 | Sourcing tier tags (R-1/R-2/R-3/H) missing from claims | Gate 9·10 (sourcing/신뢰도 tier — 확률 tier 아님) |
| 17 | PDF citation missing from creative claims | Gate 9 |
| 18 | Decision-maker action layer missing | (마스터 layer) |
5. Final Gate Keeper Report
quality_score 계산 공식 (결정론; LLM 재추론 금지):
| Gate | 가중치 | PASS | PARTIAL | SKIP | FAIL |
|---|---|---|---|---|---|
| 1–8 각 | 0.08 | 1.0 | 0.5 | 1.0 | 0.0 |
| 9, 10 각 | 0.12 | 1.0 | 0.5 | 1.0 | 0.0 |
| 11 | 0.08 | 1.0 | 0.5 | 1.0 | 0.0 |
- 가중치 합계: 8×0.08 + 2×0.12 + 1×0.08 = 0.96 (의도적으로 1.0이 아님)
- 정규화:
score = Σ(weight_i × status_score_i) / Σ(weight_i)→ 항상 0.0~1.0 보장 - 실제 계산은 §10.4
calculate_quality_score(gate_results)호출
## 🛡️ Quality Control Final Report
### Audit Summary
- Gate 1 Wagschal Unanimity: ✓ PASSED (5/5 impacts revoted)
- Gate 2 Intellectual Spaghetti: ✓ PASSED (clarity score <§10.1 값>)
- Gate 3 Premature Judgment: ⚠️ PARTIAL (P1 가정 의존성 disclosed)
- Gate 4 Correlation/Causation: ✓ PASSED (3 edges reclassified)
- Gate 5 Butterfly Effect: ✓ PASSED (2 attractor candidates noted)
- Gate 6 Timing Distinction: ✓ PASSED (S1a·S3c 재분류)
- Gate 7 Probability Comparison: ✓ PASSED (모든 노드 등급 부여)
- Gate 8 Strengths Self-Audit: ✓ PASSED (5/5 Glenn §IV strengths demonstrated)
- Gate 9 Citation Completeness: ✓ PASSED (citation_rate 100%, vague 0, fabricated 0)
- Gate 10 Reasoning Chain + SRS: ✓ PASSED (CoER chains ≥3, SRS avg <§10.2 값> ≥ 1.5, depth 6)
- Gate 11 SCBE Compliance: — SKIPPED (non-C9 cycle; auto-PASS)
### Required Disclosures
1. "본 wheel은 *creative tool*이며 truth statement 아님"
2. "edges는 likely impacts (Hume 철학에 따라 인과 자체 입증 불가)"
3. "P1 가정 변경 시 hooked chain 흔들림"
4. "[Attractor] tagged 항목은 작아 보여도 amplification 가능"
### 의사결정자 책임
"본 분석은 추가 systematic exploration의 *입력*입니다. 의사결정 시
TIA·Cross-Impact·Scenario·CLA 등 다른 method와 *반드시* 결합하십시오."
### 마스터로의 반환
status: PASSED
quality_score: <§10.4 calculate_quality_score(gate_results) 반환값>
required_revisions: 0
recommended_next: scenario-forecast for divergence nodes
6. PDF 인용 fragment
"The Futures Wheel process leads rapidly to unexpected consequences and, thus, requires a restriction on the group to prevent them from arriving at conclusions that are so speculative as to be of little worth." (Wagschal in §III.A)
"If one is not disciplined in using the Futures Wheel, one can end up with some messy 'intellectual spaghetti'." (§IV)
"One must guard against making dangerously premature judgments." (§IV)
"It can make a group or individual think they understand causal relations between the items that emerge, when it is possible that they have only identified correlations." (§IV)
"The output of a Futures Wheel should be used as a basis for further thinking, for more systematic exploration, and for the application of other techniques for probing the future. Put simply, the Futures Wheel is a creative tool that generates input to futures thinking." (§IV)
7. 마스터 입력 인터페이스
sub_skill: vision-foresight-futures-wheel-quality-control
inputs:
prior_wheel_output: { full wheel from basic-v1 or domain-v2 or others }
consequence_linker_output: { feedback_loops, contradictions } # 옵션
enabled_gates: [1,2,3,4,5,6,7,8,9,10,11] # 일부만 실행 가능
strictness:
wagschal: "Gate 1 만장일치 엄격 + Gate 9·10 100% 기준 + Gate 11 full (C9 시)"
balanced: "Gate 1 majority 허용 + Gate 9 95% 기준 + Gate 10 SRS avg ≥1.2 허용"
fast: "Gate 1·9·10·11 비활성, Gate 2~8만 적용 (속도 우선)"
cycle: "C1~C9" # Gate 11은 C9에서만 활성; 나머지 자동 SKIP
outputs:
- wagschal_audit_per_impact
- spaghetti_score # §10.1 결정론 계산값
- premature_judgment_alerts
- causation_reclassifications
- butterfly_attractors_noted
- timing_corrections
- probability_assignments
- strengths_self_audit
- citation_audit_report # Gate 9
- reasoning_chain_audit_report # Gate 10
- SRS_audit_report # Gate 10 §10.2 결정론 계산값
- MDE_compliance_report # Gate 10
- SCBE_compliance_report # Gate 11 (C9 전용; 비-C9 SKIP)
- final_gate_keeper_report
- required_disclosures
- quality_score # §10.4 결정론 계산값
- pdf_citations
8. 호출 후 마스터로 반환
sub_skill_output:
status: PASSED|REVISIONS_REQUIRED|FAILED
quality_score: <0~1; §10.4 calculate_quality_score(gate_results) 반환값>
gates_passed: [1,2,3,4,5,6,7,8,9,10,11]
gates_failed: []
gates_skipped: [] # 예: [11] — non-C9에서 SKIP (auto-PASS로 처리)
required_revisions: [...]
required_disclosures: [...]
pdf_citations: [...]
마스터는 status=REVISIONS_REQUIRED 시 해당 sub-skill 재호출하여 revise.
9. references/
| 파일 | 용도 |
|---|---|
references/wagschal_unanimity_rule.md |
Wagschal 1981 원전 정식화 |
references/intellectual_spaghetti_audit.md |
시각 명료성 알고리즘 |
references/correlation_causation_philosophy.md |
Hume·de Jouvenel 원전 + 미래학 적용 |
references/butterfly_attractor_detection.md |
chaos theory attractor 식별 |
references/18_pitfall_checklist.md |
18 pitfall 상세 점검 가이드 |
references/probability_tier_taxonomy.md |
R-1/R-2/R-3/H tier + 5-grade probability |
references/citation_completeness_audit.md |
Gate 9: citation 양식·R-1 의무·fabrication 탐지 기준 |
references/reasoning_chain_SRS_audit.md |
Gate 10: CoER 3-step 정의 + SRS 계산법 + MDE 기준 |
references/SCBE_compliance_audit.md |
Gate 11: SCBE 모드 검증 기준 (C9 전용) |
10. Python 결정론 함수 (Deterministic Utilities)
LLM이 자연어로 재추론하면 할루시네이션이 발생할 수 있는 수치 계산을 결정론적 Python으로 분리한다.
마스터 orchestrator는 아래 코드를 _qc_utils.py로 저장 후 python3 _qc_utils.py 또는 import로 호출한다.
#!/usr/bin/env python3
"""
Quality Control Deterministic Utilities
출처: vision-foresight-futures-wheel-quality-control SKILL.md §10
LLM 자연어 재추론 금지 — 이 함수들만 사용.
"""
from __future__ import annotations
# ─── §10.1 Gate 2 Visual Clarity Score ──────────────────────────────────────
def calculate_visual_clarity_score(
rings_unclear: int = 0,
no_line_types: bool = False,
unlabeled_domains: int = 0,
unmarked_crosslinks: int = 0,
feedback_unlabeled: int = 0,
) -> float:
"""결정론적 visual clarity score (0.0~1.0). LLM 재추론 금지."""
score = 1.0
score -= rings_unclear * 0.15
if no_line_types:
score -= 0.10
score -= unlabeled_domains * 0.10
score -= unmarked_crosslinks * 0.03
score -= feedback_unlabeled * 0.05
return round(max(0.0, score), 4)
def classify_spaghetti_risk(score: float) -> str:
"""low(≥0.75) / medium(0.50–0.74) / high(<0.50) 결정론 분류."""
if score >= 0.75:
return "low"
elif score >= 0.50:
return "medium"
return "high"
# ─── §10.2 Gate 10 SRS (Sewongjima Reversal Score) ─────────────────────────
# SRS = 박사님 proprietary metric; 표준 학술 용어 아님.
# Sign convention: "🟢" positive, "🔴" negative, "🟡" neutral (count 제외).
def calculate_srs(sign_sequences: list[list[str]]) -> dict:
"""
sign_sequences: 각 lineage의 sign 리스트.
예: [["🟢","🔴","🟢","🔴","🟡","🔴"], ...]
🟡 는 reversal count에서 제외.
반환: {per_lineage, global_avg, per_lineage_min_pass, global_avg_pass,
fail_condition_met, status}
"""
def _reversals(seq: list[str]) -> int:
count, prev = 0, None
for s in seq:
if s == "🟡":
continue
if prev is not None and s != prev:
count += 1
prev = s
return count
per_lineage = [_reversals(seq) for seq in sign_sequences]
n = len(per_lineage)
global_avg = round(sum(per_lineage) / n, 4) if n > 0 else 0.0
per_lineage_min_pass = all(r >= 1 for r in per_lineage)
global_avg_pass = global_avg >= 1.5
fail = global_avg < 1.0
status = "PASS" if global_avg >= 1.5 else ("REJECT" if fail else "PARTIAL")
return {
"per_lineage": per_lineage,
"global_avg": global_avg,
"per_lineage_min_pass": per_lineage_min_pass,
"global_avg_pass": global_avg_pass,
"fail_condition_met": fail,
"status": status,
}
def check_forced_reversals(
sign_sequences: list[list[str]],
depth: int = 6,
) -> dict:
"""
4차(Quaternary)·5차(Quinary)·6차(Senary) 강제 반전 ≥50% 검사.
sign_sequence 인덱스: 0=Primary, 1=Secondary, 2=Tertiary,
3=Quaternary, 4=Quinary, 5=Senary
depth < 6 이면 SKIP 반환.
"""
if depth < 6:
return {"skipped": True, "reason": f"depth={depth} < 6; MDE exception"}
reversal_pairs = [
("T_to_Q", 2, 3, "Tertiary→Quaternary 1차 강제 반전"),
("Q_to_Qn", 3, 4, "Quaternary→Quinary 2차 강제 반전"),
("Qn_to_Sn", 4, 5, "Quinary→Senary 3차 강제 반전"),
]
results: dict = {}
for label, prev_idx, curr_idx, desc in reversal_pairs:
valid = [
seq for seq in sign_sequences
if len(seq) > curr_idx
and seq[prev_idx] != "🟡"
and seq[curr_idx] != "🟡"
]
if not valid:
results[label] = {"pass": False, "reason": "no valid non-neutral lineages"}
continue
reversed_count = sum(1 for seq in valid if seq[curr_idx] != seq[prev_idx])
rate = round(reversed_count / len(valid), 4)
results[label] = {
"description": desc,
"valid_lineages": len(valid),
"reversed_count": reversed_count,
"reversal_rate": rate,
"pass": rate >= 0.5,
}
all_pass = all(v.get("pass", False) for v in results.values())
return {"checks": results, "all_pass": all_pass}
# ─── §10.3 Gate 11 SCBE Node Count & Fan-out Validation ────────────────────
def validate_node_count(frame: str, depth: int, fanout: int = 2) -> dict:
"""
frame: "STEEPS" (6 categories) | "V2" (8 categories)
depth: ring 수 (예: 6)
fanout: 노드당 자식 수 (기본 2)
반환: {frame, categories, depth, fanout, nodes_per_ring, expected_total}
"""
categories = {"STEEPS": 6, "V2": 8}.get(frame.upper(), 6)
nodes_per_ring = [categories * (fanout ** i) for i in range(depth)]
expected = 1 + sum(nodes_per_ring) # 1 = center node
return {
"frame": frame.upper(),
"categories": categories,
"depth": depth,
"fanout": fanout,
"nodes_per_ring": nodes_per_ring,
"expected_total": expected,
}
def check_fanout_uniformity(tree: dict) -> dict:
"""
tree: {node_id: {"children": [child_id, ...], "is_leaf": bool}}
반환: {compliance_rate, non_compliant_nodes, pass}
Senary leaf 제외 — 모든 비-leaf 노드는 정확히 2 children이어야 함.
"""
non_leaf = [nid for nid, data in tree.items() if not data.get("is_leaf", False)]
if not non_leaf:
return {"compliance_rate": 1.0, "non_compliant_nodes": [], "pass": True}
non_compliant = [nid for nid in non_leaf if len(tree[nid].get("children", [])) != 2]
rate = round(1.0 - len(non_compliant) / len(non_leaf), 4)
return {
"compliance_rate": rate,
"non_compliant_nodes": non_compliant,
"pass": rate == 1.0,
}
# ─── §10.2b Gate 10 MDE Compliance Check ───────────────────────────────────
EXCEPTION_KEYWORDS = ["간단히", "빠르게", "대충"]
def check_mde_compliance(
depth_reached: int,
user_message: str = "",
master_override_depth: int | None = None,
) -> dict:
"""
depth_reached: 실제 wheel 깊이 (1~6)
user_message: 사용자 원문 (예외 키워드 포함 여부 검사)
master_override_depth: 마스터가 명시한 허용 최소 깊이 (4 또는 5)
반환: {required_depth, depth_reached, exception_triggered, pass, fail_reason}
"""
required = 6
exception_triggered = False
exception_type = None
user_exception = any(kw in user_message for kw in EXCEPTION_KEYWORDS)
if user_exception:
required = 3
exception_triggered = True
exception_type = "user_keyword"
elif master_override_depth is not None and master_override_depth in (4, 5):
required = master_override_depth
exception_triggered = True
exception_type = "master_override"
ok = depth_reached >= required
return {
"required_depth": required,
"depth_reached": depth_reached,
"exception_triggered": exception_triggered,
"exception_type": exception_type,
"pass": ok,
"fail_reason": None if ok else f"depth {depth_reached} < required {required}",
}
# ─── §10.3b Gate 9 Citation Rate Check (strictness-aware) ─────────────────
def check_citation_rate(
impacts: list[dict],
strictness: str = "wagschal",
) -> dict:
"""
impacts: [{id, citation: str|None, has_number: bool, r1_source: str|None}]
strictness: "wagschal" | "balanced" | "fast"
반환: {citation_rate, vague_count, fabricated_count, pass, fail_reasons}
"""
VAGUE_PATTERNS = ["(전문가 의견)", "(연구에 따르면)", "(보고서)"]
FABRICATED_PATTERNS = ["study by", "research from", "according to"]
if strictness == "fast":
return {"skipped": True, "reason": "fast mode: Gate 9 inactive"}
total = len(impacts)
if total == 0:
return {"citation_rate": 1.0, "vague_count": 0, "fabricated_count": 0,
"pass": True, "fail_reasons": []}
with_citation = sum(1 for i in impacts if i.get("citation"))
vague = sum(1 for i in impacts
if any(p in (i.get("citation") or "") for p in VAGUE_PATTERNS))
fabricated = sum(1 for i in impacts
if any(p in (i.get("citation") or "").lower()
for p in FABRICATED_PATTERNS)
and not i.get("url_verified", False))
rate = round(with_citation / total, 4)
threshold = 1.0 if strictness == "wagschal" else 0.95 # balanced = 95%
fail_reasons = []
if rate < threshold:
fail_reasons.append(f"citation_rate {rate} < {threshold}")
if vague > 0:
fail_reasons.append(f"vague_attribution_count={vague}")
if fabricated > 0:
fail_reasons.append(f"fabricated_source_count={fabricated}")
return {
"citation_rate": rate,
"vague_count": vague,
"fabricated_count": fabricated,
"threshold_used": threshold,
"pass": len(fail_reasons) == 0,
"fail_reasons": fail_reasons,
}
# ─── §10.4 Final Quality Score ───────────────────────────────────────────────
GATE_WEIGHTS: dict[int, float] = {
1: 0.08, 2: 0.08, 3: 0.08, 4: 0.08,
5: 0.08, 6: 0.08, 7: 0.08, 8: 0.08,
9: 0.12, 10: 0.12, 11: 0.08,
}
GATE_STATUS_SCORES: dict[str, float] = {
"PASS": 1.0, "PARTIAL": 0.5, "SKIP": 1.0, "FAIL": 0.0
}
SKIP_ELIGIBLE_GATES: set[int] = {11} # 비-C9에서 자동 SKIP
def calculate_quality_score(gate_results: dict[int, str]) -> float:
"""
gate_results: {gate_number: status}
status: "PASS" | "PARTIAL" | "SKIP" | "FAIL"
SKIP_ELIGIBLE_GATES 중 gate_results에 없는 항목은 자동 SKIP으로 처리.
반환: quality_score (0.0~1.0), 가중 정규화 평균.
"""
full: dict[int, str] = {**gate_results}
for g in SKIP_ELIGIBLE_GATES:
if g not in full:
full[g] = "SKIP"
weighted_sum = 0.0
weight_used = 0.0
for gate_num, status in full.items():
w = GATE_WEIGHTS.get(gate_num, 0.08)
s = GATE_STATUS_SCORES.get(status.upper(), 0.0)
weighted_sum += w * s
weight_used += w
return round(weighted_sum / weight_used, 4) if weight_used > 0 else 0.0
# ─── 자가 테스트 ───────────────────────────────────────────────────────────────
if __name__ == "__main__":
import json
print("=== §10.1 visual_clarity_score ===")
assert calculate_visual_clarity_score() == 1.0
assert calculate_visual_clarity_score(rings_unclear=1, no_line_types=True) == 0.75
print("PASS: 1.0, 0.75")
print("\n=== §10.1 spaghetti_risk ===")
assert classify_spaghetti_risk(0.80) == "low"
assert classify_spaghetti_risk(0.60) == "medium"
assert classify_spaghetti_risk(0.40) == "high"
print("PASS: low/medium/high")
print("\n=== §10.2 calculate_srs ===")
seqs = [
["🟢", "🔴", "🟢", "🔴", "🔴", "🟢"], # reversals: 4+1 (🟢→🔴,🔴→🟢,🟢→🔴,🔴→🟢 at[4→5])
["🔴", "🔴", "🟡", "🟢", "🟢", "🔴"], # 🟡 skip → prev=🔴,curr=🟢 reversal, then 🟢→🔴
]
result = calculate_srs(seqs)
print(json.dumps(result, ensure_ascii=False, indent=2))
assert result["global_avg"] > 0
print("\n=== §10.2 check_forced_reversals (depth<6 skip) ===")
skip_result = check_forced_reversals(seqs, depth=3)
assert skip_result.get("skipped") is True
print("PASS: skipped=True for depth=3")
print("\n=== §10.3 validate_node_count ===")
r_steeps = validate_node_count("STEEPS", 6, 2)
assert r_steeps["expected_total"] == 379, f"Got {r_steeps['expected_total']}"
r_v2 = validate_node_count("V2", 6, 2)
assert r_v2["expected_total"] == 505, f"Got {r_v2['expected_total']}"
print(f"PASS: STEEPS={r_steeps['expected_total']}, V2={r_v2['expected_total']}")
print("\n=== §10.4 calculate_quality_score ===")
all_pass = {i: "PASS" for i in range(1, 12)}
assert calculate_quality_score(all_pass) == 1.0, calculate_quality_score(all_pass)
partial_3 = {**all_pass, 3: "PARTIAL"}
score = calculate_quality_score(partial_3)
assert 0.9 < score < 1.0, score
print(f"PASS: all-PASS=1.0, partial-Gate3={score}")
gate11_skip = {i: "PASS" for i in range(1, 11)} # Gate 11 absent
score_skip = calculate_quality_score(gate11_skip)
assert score_skip == 1.0, score_skip # Gate 11 auto-SKIP = PASS
print(f"PASS: Gate11 auto-SKIP score={score_skip}")
print("\n=== §10.3b check_citation_rate ===")
impacts_ok = [{"id": f"P{i}", "citation": f"[Author, 202{i}]"} for i in range(5)]
r_ok = check_citation_rate(impacts_ok, "wagschal")
assert r_ok["pass"] is True
print(f"PASS: all-cited wagschal → pass=True")
impacts_vague = impacts_ok[:4] + [{"id": "P4", "citation": "(전문가 의견)"}]
r_vague = check_citation_rate(impacts_vague, "wagschal")
assert r_vague["pass"] is False and r_vague["vague_count"] == 1
print(f"PASS: vague → pass=False, vague_count={r_vague['vague_count']}")
# balanced: 4/5 = 80% < 95% threshold → fail
impacts_missing = impacts_ok[:4] + [{"id": "P4", "citation": None}]
r_bal = check_citation_rate(impacts_missing, "balanced")
assert r_bal["pass"] is False # 0.80 < 0.95
print(f"PASS: balanced 80% citation → pass=False (threshold=0.95)")
r_fast = check_citation_rate(impacts_ok, "fast")
assert r_fast.get("skipped") is True
print(f"PASS: fast mode → skipped=True")
print("\n=== §10.2b check_mde_compliance ===")
r_no_exc = check_mde_compliance(depth_reached=4)
assert r_no_exc["pass"] is False and r_no_exc["required_depth"] == 6
print(f"PASS: depth=4 no exception → fail (required=6)")
r_user_exc = check_mde_compliance(depth_reached=3, user_message="빠르게 해줘")
assert r_user_exc["pass"] is True and r_user_exc["required_depth"] == 3
print(f"PASS: depth=3 + '빠르게' → pass (required=3)")
r_master = check_mde_compliance(depth_reached=5, master_override_depth=5)
assert r_master["pass"] is True and r_master["exception_type"] == "master_override"
print(f"PASS: depth=5 + master_override=5 → pass")
r_full = check_mde_compliance(depth_reached=6)
assert r_full["pass"] is True
print(f"PASS: depth=6 no exception → pass")
print("\n모든 자가 테스트 PASS")