schema_version: formula_domain.v1
source: C:\Temp\data_feed\spec\13_formula_registry.yaml
domain: governance
meta:
  note: >
    governance/todo/v8_9_p1_adoption_plan.yaml P1-C.
    source: suggest/quant_investment_engine_v8_9_portfolio_optimizer_canonical_refactored.yaml:model_governance_v8_9
    이 도메인은 종목/팩터 수준 promotion(spec/57_shadow_promotion_scorecard.yaml)과는 별개로
    전략 execution_mode 단계(AUDIT_ONLY→SHADOW→PILOT→LIVE_LIMITED→LIVE_FULL) 전체를 다룬다.
formulas:
  MODEL_GOVERNANCE_KILL_SWITCH_V1:
    purpose: >
      data_quarantine_rate, implementation_shortfall, T5_hit_rate, calibration_error,
      drawdown 5개 지표를 감시해 기준 이탈 시 execution_mode를 자동으로 한 단계 강등한다.
      LLM이나 운영자가 "이번엔 괜찮을 것"이라는 서사로 강등을 보류하는 것을 금지한다.
      (governance/todo/v8_9_p1_adoption_plan.yaml P1-C.1,
      source: suggest/quant_investment_engine_v8_9_portfolio_optimizer_canonical_refactored.yaml:risk_controls_v8_9.kill_switches,
      model_governance_v8_9.automatic_demotion)
    applicable: 매 의사결정 사이클 시작 전. PORTFOLIO_TRANSITION_UTILITY_V1보다 먼저 평가되어 execution_mode를 확정한다.
    promotion_ladder: [AUDIT_ONLY, SHADOW, PILOT, LIVE_LIMITED, LIVE_FULL]
    inputs:
    - field: data_quarantine_rate_pct
      unit: percent
      source: tools/build_yaml_code_coverage_v1.py 계열 — 결측/충돌로 quarantine된 입력 비율
    - field: implementation_shortfall_ratio
      unit: ratio
      note: 실제 슬리피지 / 기대 슬리피지. 2.0 초과 시 위반.
    - field: t5_hit_rate_pct
      source: spec/29_backtest_harness_contract.yaml:current_metrics.direction_accuracy.t5_op_rate
      unit: percent
    - field: t5_sample_count
      source: spec/29_backtest_harness_contract.yaml:current_metrics.direction_accuracy.t5_op_rate.n_sample
      unit: count
    - field: calibration_error
      source: spec/calibration_registry.yaml
      unit: ratio
    - field: calibration_error_limit
      unit: ratio
    - field: account_mdd_pct
      unit: percent
    - field: account_mdd_budget_pct
      source: spec/risk/aggregate_risk.yaml
      unit: percent
    kill_switch_conditions:
    - id: data_quarantine_rate_above_5pct
      condition: data_quarantine_rate_pct > 5.0
    - id: implementation_shortfall_above_2x_expected
      condition: implementation_shortfall_ratio > 2.0
    - id: t5_hit_rate_below_50pct_for_30_trades
      condition: t5_sample_count >= 30 AND t5_hit_rate_pct < 50.0
    - id: calibration_error_above_limit
      condition: calibration_error > calibration_error_limit
    - id: unexpected_drawdown_breach
      condition: account_mdd_pct > account_mdd_budget_pct
    demotion_rule: >
      kill_switch_conditions 중 하나라도 true이면 execution_mode를 promotion_ladder에서
      현재 단계 -1 (한 단계만 강등). AUDIT_ONLY는 더 이상 강등되지 않는다(최저 단계).
      여러 조건이 동시에 발동해도 1단계만 강등(과잉반응 방지) — 단, 재평가 사이클마다 조건이
      계속 true이면 추가로 1단계씩 강등된다.
    promotion_rule: >
      kill_switch_conditions 전부 false이고 spec/57_shadow_promotion_scorecard.yaml의
      promotion_gate_criteria(해당 단계 전환 기준)를 만족할 때만 한 단계 승급. 자동 승급 없음 —
      승급은 operator_override 기록을 동반해야 한다(v8.9 V89_039).
    output:
      field: execution_mode
      unit: enum
    additional_outputs:
    - kill_switch_triggered
    - kill_switch_reason_codes
    - execution_mode_changed
    missing_policy: 입력 지표 중 하나라도 null이면 해당 kill switch는 평가 불가로 PARTIAL 표기하고, 평가 가능한 지표만으로 판정한다. 모든 지표 null이면 execution_mode 변경 없이 DATA_MISSING.
    canonical_ref: spec/57_shadow_promotion_scorecard.yaml
    implementation: tools/build_model_governance_kill_switch_v1.py
    owner: quant_team
    lifecycle_state: shadow
    input_fields:
    - data_quarantine_rate_pct
    - implementation_shortfall_ratio
    - t5_hit_rate_pct
    - t5_sample_count
    - calibration_error
    - calibration_error_limit
    - account_mdd_pct
    - account_mdd_budget_pct
    output_fields:
    - execution_mode
    - kill_switch_triggered
    - kill_switch_reason_codes
    golden_cases:
    - V89_035_model_kill_switch_hit_rate
    - V89_036_model_kill_switch_slippage
    - V89_037_data_quarantine_rate
    activation_threshold:
      min_t20_sample: 30
    retirement_condition: performance_degradation
  IMMUTABLE_DECISION_LEDGER_V1:
    purpose: >
      모든 의사결정을 append-only로 기록해 사후 재구성과 T1/T5/T20 성과 귀속을 가능하게 한다.
      기존 레코드 수정·삭제를 금지하며, 동일 decision_id 재기록 시도는 거부한다.
      (governance/todo/v8_9_p2_adoption_plan.yaml P2-C,
      source: suggest/quant_investment_engine_v8_9_portfolio_optimizer_canonical_refactored.yaml:model_governance_v8_9.immutable_decision_log_required_fields)
    applicable: PORTFOLIO_TRANSITION_UTILITY_V1 또는 TRANSITION_SET_ENUMERATOR_V1이 selected_transition을 확정한 직후.
    required_fields:
    - decision_id
    - timestamp
    - engine_version
    - input_hash_bundle
    - execution_mode
    - candidate_ids
    - selected_transition_id
    - hard_blocks
    - transition_utility_krw
    - operator_override
    - order_ids
    - fill_prices
    - slippage
    - T1_return
    - T5_return
    - T20_return
    - MAE
    - MFE
    append_only_rule: >
      decision_id가 이미 ledger에 존재하면 신규 append를 거부하고 DUPLICATE_DECISION_ID 오류를 반환한다.
      기존 레코드의 필드 값을 변경하는 호출은 없다 — T1/T5/T20/MAE/MFE는 별도의 update_outcome
      append(새 레코드, 동일 decision_id 참조)로만 추가하고 원본 decision 레코드는 불변으로 둔다.
    inputs:
    - field: decision_id
      unit: string
    - field: engine_version
      unit: string
    - field: input_hash_bundle
      unit: string
    - field: execution_mode
      unit: enum
    - field: candidate_ids
      unit: list_of_string
    - field: selected_transition_id
      unit: string_or_null
    - field: transition_utility_krw
      unit: number_or_null
    output:
      field: ledger_append_status
      unit: 'enum: APPENDED | DUPLICATE_DECISION_ID | REJECTED_MISSING_FIELDS'
    missing_policy: required_fields 중 하나라도 없으면 REJECTED_MISSING_FIELDS — 빈 문자열/0으로 채워 append 금지.
    canonical_ref: spec/formulas/domains/portfolio.yaml:PORTFOLIO_TRANSITION_UTILITY_V1
    implementation: tools/build_immutable_decision_ledger_v1.py
    owner: quant_team
    lifecycle_state: shadow
    input_fields:
    - decision_id
    - engine_version
    - input_hash_bundle
    - execution_mode
    - candidate_ids
    - selected_transition_id
    - transition_utility_krw
    output_fields:
    - ledger_append_status
    golden_cases:
    - V89_039_operator_override
    activation_threshold:
      min_t20_sample: 30
    retirement_condition: performance_degradation
