meta:
  title: "은퇴자산포트폴리오 — 등급·보고서·HTS 출력 스키마 명세"
  parent_file: "RetirementAssetPortfolio.yaml"
  version: "2026-05-18-F3_zero_adjective"
  language: "ko-KR"
  timezone: "Asia/Seoul"
  has_code_implementation: true
  code_path: "tools/validate_specs.py"
  purpose: "메인 manifest에서 로드되는 구조화 규칙 명세 파일."
  machine_readable_schema: "schemas/output_schema.json"

json_output_contract:
  schema_file: "schemas/output_schema.json"
  schema_version: "2026-05-15-F6-compat-output"
  purpose: "자동화 연동·검증용 최종 JSON 출력 계약. 사람용 상세 보고서 양식보다 기계 판독 우선."
  precedence: "JSON 출력이 요청되면 이 계약을 우선하고, 표/문장 보고서는 RetirementAssetPortfolioReportTemplate.yaml을 보조로 사용한다."
  two_phase_rendering:
    phase_1_validation_payload: "먼저 schemas/output_schema.json에 맞는 구조화 payload를 완성하고 null·정수·enum·prohibited_calculations를 검증한다."
    phase_2_human_report: "검증된 payload의 값만 RetirementAssetPortfolioReportTemplate.yaml 표에 매핑한다."
    prohibition:
      - "검증된 JSON 또는 동등한 구조화 표 없이 산문 보고서에서 주문 결론을 먼저 작성 금지"
      - "표에 없는 계좌·현금·수량·평단 숫자를 본문 문장으로 새로 생성 금지"
      - "schema enum 밖의 주문구분·모드·검산상태 용어 사용 금지"
  required_top_level_fields:
    - "schema_version"
    - "analysis_date"
    - "analysis_scope"
    - "data_basis"
    - "capture_read_ledger"
    - "portfolio_decision"
    - "scores"
    - "position_sizing"
    - "risk_gate"
    - "data_completeness_matrix"
    - "decision_trace"
    - "orders"
    - "prohibited_calculations"
    - "triggered_rules"
    - "missing_data"
    - "invalidation_conditions"
    - "evidence"
    - "rule_ids_used"
    - "rules_used"
    - "summary"
  hard_validation_rules:
    - "scores는 quality/valuation/momentum/risk/strategy/portfolio_fit/total 점수를 포함한다. 산출 불가 시 null과 missing_data 사유를 함께 남긴다."
    - "position_sizing은 최종 정수수량 또는 NO_QUANTITY/BLOCKED 사유를 명시한다."
    - "triggered_rules와 rules_used에는 적용한 파일 경로와 YAML path를 기록한다."
    - "rule_ids_used에는 HF001 같은 짧은 rule_id를 배열로 중복 기록해 타 도구 호환성을 유지한다."
    - "evidence에는 수치·출처·기준시각·데이터태그를 남긴다."
    - "invalidation_conditions에는 무효화 조건과 후속 행동을 명시한다."
    - "orders[].quantity, stop_quantity, take_profit_quantity는 정수 또는 null만 허용한다."
    - "validation_status=PASS인 BUY 주문은 지정가·수량·손절가·손절수량·익절가·익절수량을 모두 포함해야 한다."
    - "validation_status=PASS인 SELL/STOP_LOSS/TAKE_PROFIT/TRAILING_STOP 주문은 capture_read_ledger에서 확인한 current_holding_quantity, average_cost_krw, current_price_krw를 함께 포함해야 한다."
    - "데이터 부족으로 산출하지 못한 값은 임의 숫자 대신 null과 prohibited_calculations 사유로 남긴다."
    - "decision_trace에는 상태별 check_id, rule_ref, inputs_used, result, selected_action, blocked_actions, missing_inputs, tie_breaker_applied를 남긴다."

recommendation_grade:
  # [proposal_118 / 2026-05-15] canonical 지정 — A/B/C/D 라벨 단일 기준
  canonical: true  # 이 섹션이 기준. sector_model.grade는 alias.
  A: "즉시 가능. 원시 데이터로 데이터·수급·실적·가격·유동성·기대수익비 충족, 정수 수량 산출 가능"
  B: "지정가 대기. 질은 양호하나 가격·손절폭·과열 또는 일부 데이터 확인 대기"
  C: "관찰. 일부 데이터 미확인, 프록시 중심, 기대수익비 부족, 수량 0주"
  D: "제외. 실적 하향, 수급 이탈, 유동성 부족, 테마 급등, 신용 급증+외국인 매도"
  mode_policy:
    A: "lead_mode 우선 허용. 단, buy_proposal_template.validation 4개 세트 필수."
    B: "hybrid_mode 우선. 선행형 시범진입 또는 후행형 본진입 중 하나만 선택하고 혼용 시 모드 표기 필수."
    C: "lag_mode만 허용. 선행형 진입 금지, 관찰 또는 축소 중심."
    D: "모든 매수 제안 금지. 데이터 보강 또는 제외."
  display_policy:
    A: ["sell_priority_decision_table", "concise_hts_input_sheet", "immediate_execution_playbook", "buy_proposal_output_examples"]
    B: ["sell_priority_decision_table", "concise_hts_input_sheet", "immediate_execution_playbook", "buy_proposal_output_examples", "sell_proposal_output_examples"]
    C: ["sell_priority_decision_table", "concise_hts_input_sheet", "sell_proposal_output_examples"]
    D: ["concise_hts_input_sheet"]
    output_sequence:
      # ── [2026-05-20_I1] 필수 선행 섹션 (QEH_AUDIT_BLOCK 이전 출력 의무) ──
      step_0a: "routing_serving_trace"       # G4/I1 필수: request_route/bundle/entrypoint/json_validation_status
      step_0b: "QEH_AUDIT_BLOCK"             # G4/I1 필수: TOTAL_HEAT_V1·CASH_RATIOS_V1 등 검산 표
      # ── Section A 하드 원장 ─────────────────────────────────────────────
      step_1: "capture_read_ledger"
      step_2: "data_completeness_matrix"
      step_3: "backdata_feature_bank_table"
      step_4: "benchmark_relative_harness_table"
      step_4b: "index_relative_health_table"
      step_5: "alpha_lead_table"
      step_5b: "entry_freshness_gate_table"
      step_6: "anti_distribution_table"
      step_7: "profit_preservation_table"
      step_7b: "sell_value_preservation_gate_table"
      step_8: "smart_cash_raise_table"
      step_9: "execution_quality_table"
      step_10: "order_quantity_4stage_gate"
      step_11: "decision_trace_table"
      step_12: "sell_priority_decision_table"
      step_13: "current_holdings_analysis_report_template"
      step_14a: "concise_hts_input_sheet"     # validation_status=PASS 행만 기재
      step_14b: "reference_price_ledger"      # [I4/HS010] WATCH 감시 원장 — 주문 아님, HTS 입력 금지
      step_15: "engine_feedback_loop_report"
      step_15b: "prediction_evaluation_improvement_report"
      step_16: "alpha_feedback_loop_report"
      step_17: "immediate_execution_playbook"
      step_18: "market_leader_screening_report_template"
      step_19: "market_micro_macro_flow_scenario_report_template"
      step_20: "buy_proposal_output_examples"
      step_21: "sell_proposal_output_examples"
      step_22: "unified_order_sheet_example"
      step_23: "data_flow_analysis_report"
      step_24: "rebalancing_report_template"
      step_25: "market_context_learning_note"
      step_26: "core_satellite_timing_gate_table"
      step_27: "기타 보조 표"
  current_holdings_analysis_report_template: "activation.trigger 충족 또는 포지션 리뷰 주기 도래 시 모든 등급에서 조건부 노출한다."
  market_leader_screening_report_template: "sector_flow 또는 quant_feed 갱신 시 모든 등급에서 조건부 노출한다."
  market_micro_macro_flow_scenario_report_template: "macro_snapshot 또는 sector_flow 갱신 시 모든 등급에서 조건부 노출한다."
  rebalancing_report_template: "activation.trigger 충족 시 모든 등급에서 조건부 노출한다."
  sell_priority_decision_table: "SELL/TRIM/ROTATE 후보가 2개 이상이거나 cash_floor·중복노출 매도 후보가 동시에 있을 때 조건부 노출한다. 활성 시 current_holdings_analysis_report_template보다 먼저 노출한다."
  market_context_learning_note: "사용자가 학습형 설명을 원하거나 주간/월간 리뷰 보고서일 때 조건부 노출한다. 단, 주문표·검산표보다 뒤에만 둔다."
  note: "등급별 출력은 위 목록만 노출한다. 목록 외 표는 숨기고, 출력을 늘리기 위해 등급을 상향 조작하지 않는다. 주도주 후보·보유주 분석·미시거시흐름·리밸런싱·학습 해설 표는 발동 조건 충족 시에만 예외적으로 노출한다."
  sequence_rule: "상단에서 하단으로 읽히는 순서가 우선이며, 등급별 display_policy에 없는 표는 뒤에 있어도 기본 출력 금지."
  prohibition:
    - "등급과 무관하게 손절가·손절수량·익절가·익절수량 미포함 매수 제안 금지"
    - "A등급이라고 해서 대량 일괄매수 허용하지 않음"
    - "C등급에서 선행형 돌파 추격 금지"

# ── [2026-05-20_I1] 사람용 보고서 필수 섹션 (G4/I1 강제화) ─────────────────────
human_report:
  required_sections:
    # routing_serving_trace는 QEH_AUDIT_BLOCK보다 먼저 출력해야 한다.
    # 누락 시 BLOCKED_REPORT 처리. (G4 감사 문서 Section 3 요건)
    - name: "routing_serving_trace"
      must_precede: "QEH_AUDIT_BLOCK"
      required_fields:
        - "request_route"
        - "bundle_selected"
        - "prompt_entrypoint"
        - "json_validation_status"
        - "capture_required"
        - "cash_ledger_basis"
      missing_action: "BLOCKED_REPORT — routing_serving_trace 없이 QEH_AUDIT_BLOCK 출력 금지"
    - name: "QEH_AUDIT_BLOCK"
      must_precede: "concise_hts_input_sheet"
      required_formulas:
        - "TOTAL_HEAT_V1"
        - "CASH_RATIOS_V1"
        - "SELL_PRIORITY_V1"
      optional_formulas:
        - "GOAL_RETIREMENT_V1"
        - "CASH_SHORTFALL_V1"
      missing_action: "INVALID_MISSING_AUDIT — HTS 주문표 전체 BLOCKED"
    - name: "backdata_feature_bank_table"
      must_precede: "alpha_lead_table"
      required_formulas: ["BACKDATA_FEATURE_BANK_V1"]
      missing_action: "BACKDATA_MISSING — GAS 자동 수집 우선 원장 없으면 fallback만 사용"
    - name: "benchmark_relative_harness_table"
      must_precede: "alpha_lead_table"
      required_formulas: ["BENCHMARK_RELATIVE_TIMESERIES_V1", "SATELLITE_ALPHA_QUALITY_GATE_V1", "SATELLITE_AGGREGATE_PNL_GATE_V1", "CASH_CREATION_PURPOSE_LOCK_V1"]
      missing_action: "BRT_HARNESS_MISSING — 위성 BUY/교체매수/현금창출 매도 판단 BLOCKED"
    - name: "index_relative_health_table"
      must_precede: "alpha_lead_table"
      required_formulas: ["INDEX_RELATIVE_HEALTH_GATE_V1"]
      missing_action: "INDEX_RELATIVE_HEALTH_MISSING — 지수 대비 괴리 종목 BUY 판단 BLOCKED"
    - name: "decision_trace_table"
      must_precede: "concise_hts_input_sheet"
      missing_action: "주문표 출력 전 decision_trace_table 필수"
    - name: "alpha_lead_table"
      must_precede: "concise_hts_input_sheet"
      required_formulas: ["ALPHA_LEAD_SCORE_V1", "FOLLOW_THROUGH_CONFIRM_V1"]
      missing_action: "APEX_ALPHA_MISSING — BUY 주문표 전체 BLOCKED"
    - name: "entry_freshness_gate_table"
      must_precede: "concise_hts_input_sheet"
      required_formulas: ["BREAKOUT_QUALITY_GATE_V2", "FOLLOW_THROUGH_CONFIRM_V1", "PRE_DISTRIBUTION_EARLY_WARNING_V1", "ALPHA_EVALUATION_WINDOW_V1"]
      missing_action: "ENTRY_FRESHNESS_MISSING — 뒷북/추격 BUY 판단 BLOCKED"
    - name: "anti_distribution_table"
      must_precede: "concise_hts_input_sheet"
      required_formulas: ["DISTRIBUTION_RISK_SCORE_V1"]
      missing_action: "APEX_DISTRIBUTION_MISSING — BUY/ADD_ON 전체 BLOCKED"
    - name: "profit_preservation_table"
      must_precede: "concise_hts_input_sheet"
      required_formulas: ["PROFIT_PRESERVATION_STATE_V1"]
      missing_action: "APEX_PROFIT_LOCK_MISSING — 수익 포지션 TP/TRAILING 출력 BLOCKED"
    - name: "sell_value_preservation_gate_table"
      must_precede: "concise_hts_input_sheet"
      required_formulas: ["SMART_CASH_RAISE_V2", "K2_STAGED_REBOUND_SELL_V1", "RATCHET_TRAILING_AUTO_V1", "ANTI_WHIPSAW_HOLD_GATE_V1"]
      missing_action: "SELL_VALUE_PRESERVATION_MISSING — 회복 보존 매도 판단 BLOCKED"
    - name: "smart_cash_raise_table"
      must_precede: "concise_hts_input_sheet"
      required_formulas: ["SMART_CASH_RAISE_PLAN_V1", "SELL_QUANTITY_ALLOCATOR_V1"]
      missing_action: "APEX_CASH_RAISE_MISSING — 현금확보 SELL/TRIM 주문표 BLOCKED"
    - name: "execution_quality_table"
      must_precede: "concise_hts_input_sheet"
      required_formulas: ["EXECUTION_QUALITY_GUARD_V1", "LIMIT_PRICE_POLICY_V1"]
      missing_action: "APEX_EXECUTION_QUALITY_MISSING — HTS 주문표 PASS 금지"
    - name: "proposal_reference_sheet"
      must_precede: "concise_hts_input_sheet"
      required_formulas: ["SELL_QUANTITY_ALLOCATOR_V1", "BUY_QUANTITY_V1", "STOP_PRICE_CORE_V1", "TAKE_PROFIT_LADDER_V2"]
      missing_action: "PROPOSAL_SHEET_MISSING — 실행 차단 상황에서도 사용자 판단용 제안표 필수"
    - name: "watch_release_checklist"
      must_precede: "satellite_buy_proposal_sheet"
      missing_action: "WATCH 해제 조건 체크리스트 누락"
    - name: "satellite_buy_proposal_sheet"
      must_precede: "core_satellite_timing_gate_table"
      missing_action: "위성 신규 매수 제안 원장 누락"
    - name: "core_satellite_timing_gate_table"
      must_precede: "engine_feedback_loop_report"
      required_formulas: ["BUY_TIMING_SUITABILITY_V1", "T1_FORCED_SELL_RISK_V1", "SELL_CONFLICT_AWARE_RECOMMENDATION_V1"]
      missing_action: "CORE_SAT_TIMING_MISSING — core_satellite 후보를 BUY 추천으로 해석 금지"
    - name: "engine_feedback_loop_report"
      required_formulas: ["PROPOSAL_EVALUATION_LOOP_V1"]
      missing_action: "FEEDBACK_LOOP_MISSING — 전일 제안값과 다음날 결과 비교 원장 누락"
    - name: "prediction_evaluation_improvement_report"
      must_precede: "alpha_feedback_loop_report"
      missing_action: "PREDICTION_EVAL_IMPROVEMENT_MISSING — 예측 평가·개선 하네스 누락"
    - name: "alpha_feedback_loop_report"
      required_formulas: ["ALPHA_FEEDBACK_LOOP_V1"]
      missing_action: "AFL_MISSING — SAQG 임계값 피드백 권고 원장 누락"
  watch_ledger:
    section_name: "reference_price_ledger"
    title_required: "WATCH 감시 원장 — 주문 아님, HTS 입력 금지"
    applies_to: "order_blueprint_json rows where validation_status != PASS"
    allowed_columns:
      - "ticker"
      - "name"
      - "reference_stop_price"
      - "reference_price_basis"
      - "reference_tp_state"
      - "hts_allowed"
      - "reason_code"
    forbidden_columns:
      - "지정가"
      - "손절가"
      - "익절가"
      - "매도가"
      - "주문가"
      - "주문수량"
      - "손절수량"
      - "익절수량"
      - "매도수량"
      - "주문금액"
    fill_rule:
      - "reference_tp_state는 tp1/tp2 상태를 함께 표현한다. 예: tp1=PENDING; tp2=PENDING."
    violation_action: "INVALID_COLUMN — [HS010-I4] 위반"
  auto_downgrade_rule:  # [R1] 완전 정의. position_review_cycle은 단방향 참조만 한다.
    detection: "capture_read_ledger 또는 performance_evidence 로그에 해당 위성의 마지막 점검 기록일로부터 10거래일 이상 경과하거나 점검 기록 자체가 없는 포지션"
    condition: "위성 포지션 점검 기록 없이 10거래일 이상 경과"
    action: "해당 위성 등급 자동 C로 강등"
    regrade_protocol: "C 강등 해제는 수요일 정기점검(position_review_cycle.wednesday_check) 완료 기록 후에만 허용. 단순 보유 지속으로 자동 복구 금지."
    escalation_path:
      D_plus_10: "점검 기록 없이 10거래일 경과 → C등급 강등"
      D_plus_20: "추가 10거래일 점검 기록 없으면 stop_loss.time_stop satellite 규칙 즉시 적용"
      D_plus_30: "time_stop 미적용 시 emergency 청산 규칙 적용 검토"

output_presentation:
  language_policy:
    default_locale: "ko-KR"
    internal_contract_language: "EN"
    user_visible_language: "KO"
    allow_english_only_for:
      - "ticker"
      - "formula_id"
      - "file_path"
      - "command"
      - "json_key"
      - "rule_id"
    prohibit_english_in:
      - "section_title"
      - "decision_summary"
      - "order_reason"
      - "validation_summary"
      - "human_status_label"
    rendering_rule:
      - "내부 계약값·JSON key·공식 ID는 영문 유지 가능"
      - "사용자 노출 표 제목·상태문구·설명문은 한글 우선"
      - "PASS/FAIL/BLOCKED/BUY/SELL/TRIM 등 canonical enum은 사람이 읽는 보고서에서는 한글 표시값으로 치환"
    validation_rule:
      - "render-report 이후 validate_report_quality에서 영문 상태 토큰 노출을 차단한다."
      - "prediction_evaluation_improvement_report의 gap 경고가 '경고'이면 보고서를 FAIL 처리한다."
      - "yaml/gs/json/py gap matrix의 커버리지는 각 항목 100%를 목표로 하며, 100% 미달 항목 존재 시 배포 차단한다."
  proposal_execution_separation:
    proposal_layer:
      rule: "가격·수량 입력이 충족되면 시장 개장 여부와 무관하게 proposal_reference_sheet를 출력한다."
      outputs:
        - "proposed_limit_price_krw"
        - "proposed_quantity"
        - "proposed_quantity_basis"
        - "stop1_price_krw"
        - "stop1_quantity"
        - "stop2_price_krw"
        - "stop2_quantity"
        - "stop3_price_krw"
        - "stop3_quantity"
        - "tp1_price_krw"
        - "tp1_quantity"
        - "tp2_price_krw"
        - "tp2_quantity"
        - "tp3_price_krw"
        - "tp3_quantity"
      price_selection_rule:
        - "SELL/TRIM/방어 제안은 proposed_limit_price_krw=prices_json.stop_price 우선"
        - "TAKE_PROFIT 제안은 proposed_limit_price_krw=prices_json.tp1_price 우선, 없으면 tp2_price"
        - "BUY 제안은 proposed_limit_price_krw=order_blueprint_json.limit_price_krw 우선"
        - "WATCH/HOLD는 주문가가 아닌 참고 방어가를 표시하고, 실행가능여부=proposal_only로 고정"
      quantity_selection_rule:
        - "SELL/TRIM 제안은 proposed_quantity=sell_quantities_json.sell_qty 우선"
        - "BUY 제안은 proposed_quantity=buy_qty_inputs_json.final_qty 우선"
        - "WATCH/HOLD는 즉시 주문 수량이 아니라 참고 수량임을 proposed_quantity_basis에 명시"
      ladder_rule:
        - "TP1/TP2/TP3 가격·수량은 tp_quantity_ladder_json 및 prices_json을 우선 사용한다."
        - "STOP1/STOP2 수량은 stop_loss.core/satellite quantity_rule을 따른다. core=50/50, satellite=70/30."
        - "STOP3는 profit_preservation_json.auto_trailing_stop 또는 protected_stop_price가 있을 때만 채운다."
    execution_layer:
      rule: "HTS 즉시 입력 가능 여부는 concise_hts_input_sheet와 execution_status로 별도 판정한다."
      statuses:
        - "proposal_only"
        - "execution_wait"
        - "execution_ready"
      rendering_rule:
        - "proposal_reference_sheet는 사용자 판단용 참고표이며 주문 실행표가 아니다."
        - "validation_status가 PASS가 아니어도 proposal_reference_sheet에는 후보 행과 차단 사유를 남겨야 한다."
        - "proposal_reference_sheet와 concise_hts_input_sheet는 우선순위그룹 / 우선순위로 정렬 상태를 명시해야 한다."
        - "concise_hts_input_sheet는 validation_status=PASS 행만 유지한다."

korean_display_labels:
  purpose: >
    보고서 출력 시 영문 코드·레이블을 한글로 표시하기 위한 매핑 규칙.
    LLM은 사용자에게 보고서를 출력할 때 이 매핑을 참조해 한글 표기로 대체한다.
    JSON 자동화 출력의 필드 키·enum 값은 이 규칙의 적용 대상이 아니다.
  apply_rule: "사람이 읽는 표의 셀 값·컬럼 레이블·설명 문장에서 아래 영문이 나타나면 한글로 대체한다."
  status_codes:
    PASS: "통과"
    FAIL: "실패"
    OK: "정상"
    PARTIAL: "부분"
    MISSING: "누락"
    BLOCKED: "차단"
    DATA_MISSING: "데이터누락"
    NO_QUANTITY: "수량미산출"
    CAPTURE_READ_FAILED: "판독실패"
    BUY_BLOCKED_TRIM_REQUIRED: "매수차단(축소필요)"
    CASH_GATE_PASS: "현금게이트통과"
    CONDITIONAL_HOLD: "조건부보류"
    SELL_ALLOWED: "매도허용"
    INFLOW_MODERATE: "유입보통"
    INFLOW_STRONG: "유입강"
    OUTFLOW_ALERT: "유출경고"
    OUTFLOW_CAUTION: "유출주의"
    NEUTRAL: "중립"
    REDUCE: "축소"
    SUSPEND: "중단"
  mode_labels:
    lead: "선행형"
    lead_mode: "선행형"
    lag: "후행형"
    lag_mode: "후행형"
    hybrid: "혼합형"
    hybrid_mode: "혼합형"
  data_status_labels:
    "[D]데이터상태 (OK/PARTIAL/MISSING)": "[D]데이터상태 (정상/부분/누락)"
    "Pass/Fail": "통과/실패"
    Price_OK: "가격정상"
    Price_Warn: "가격주의"
    Flow_OK: "수급정상"
  exclusions:
    - "JSON 출력 필드 키 (schema_version, analysis_date 등)"
    - "YAML 파일 내부 key 이름"
    - "rule_id 코드 (HF001 등)"
    - "수식·공식 내 변수명 (Expected_Edge, ATR20, CSCS 등)"
    - "종목 티커·계좌명"

output_format:
  principle: "실행 보고서는 spec/00_execution_contract.yaml의 master_prohibitions, hard_stops, order_validation_contract를 우선한다."
  prose_control:
    rule: "투자 판단 보고서는 표 중심으로 렌더링하며, 임의의 서론·본론·결론형 산문 헤더로 필수 표를 대체하지 않는다."
    allowed_text: "각 표의 근거·매도사유·다음확인사항 컬럼 안에 1~2문장 이내로만 작성한다. market_context_learning_note는 교육 목적상 항목별 2~3문장까지 허용하되 새 주문수량·가격·현금 숫자를 생성하지 않는다."
    zero_adjective_rule:  # [2026-05-18_AUDIT_FIX_V1] Zero-Adjective 리포팅 엔진
      purpose: >
        감성적 형용사·감정적 표현을 투자 판단 근거로 사용하는 것을 차단한다.
        모든 형용사는 수치화된 상태 코드(Status Code)로 대체되어야 한다.
        "상황이 급박해서", "용기가 필요한", "단순하다", "뚜렷하다" 등의 표현은
        데이터 기반 코드로 대체하지 않으면 근거로 인정하지 않는다.
      blocked_adjectives:
        - {term: "약세", replacement: "[SEC_STATUS: WEAK] 또는 [RW_SCORE: N]"}
        - {term: "강세", replacement: "[SEC_STATUS: STRONG] 또는 [RS_PCT: N%]"}
        - {term: "급락", replacement: "[RET_5D: -N%] 또는 [CRASH_TIER: N]"}
        - {term: "급등", replacement: "[RET_5D: +N%] 또는 [SURGE_DETECTED: true]"}
        - {term: "위험", replacement: "[RISK_LEVEL: HIGH] 또는 [TOTAL_HEAT: N%]"}
        - {term: "용기", replacement: "사용 금지 — 규칙·수치 근거 없는 감정 호소"}
        - {term: "급박", replacement: "사용 금지 — P4 위반 트리거 패턴"}
        - {term: "단순하다", replacement: "[RULE_ID: X] 적용 결과로 대체"}
        - {term: "충분하다", replacement: "[CASH_RATIO: N%] >= [FLOOR: N%] 조건 결과로 대체"}
        - {term: "뚜렷하다", replacement: "[SIGNAL_CONFIRMED: true] 또는 수치 조건으로 대체"}
      violation_action: >
        위 표현이 근거·제안근거·매도사유 컬럼에 감정 호소 목적으로 사용된 경우
        해당 컬럼을 [ADJECTIVE_VIOLATION: 상태코드 재기재 필요]로 표시하고
        validation_status=MANUAL_CHECK_REQUIRED로 강등한다.
      exception: "market_context_learning_note(교육 해설 블록)는 가독성 목적의 형용사 허용. 단, 주문수량·가격·현금 판단에는 적용 금지."
    narrative_override_ban:
      rule: >
        근거·제안근거·매도사유 컬럼은 "Rule_ID 또는 formula_ID + 산출값" 단답식만 허용.
        서술형 이유를 사용해 규칙 적용을 면제·유보·완화하는 행위 절대 금지.
      prohibited_patterns:
        - pattern: "심리적 지지선·차트 지지선·임의 보호가"
          reason: "미등록 가격 근거 — P7_price_formula_id_required 위반"
        - pattern: "뉴스·모멘텀 스토리·수주 기대감·이슈"
          reason: "수급 공식 외 서술 근거 — 규칙 우회 서술"
        - pattern: "~이기 때문에 손절 보류, ~이므로 전량 매도 불필요"
          reason: "규칙 면제·연기 서술 — P3_no_risk_block_override 위반"
        - pattern: "현금이 충분하므로 매수 추가, 현금 목표 달성으로 추가 매도 불필요"
          reason: "Total_Heat 초과 시에도 현금 논리로 위험 규칙 우회 — P3 위반"
      correct_format: "[formula_ID 또는 Rule_ID]:[산출값 또는 조건결과]"
      correct_examples:
        - "STOP_PRICE_CORE_V1:23,200원 | ATR20=640"
        - "RW_EXIT:합계4 | 청산비율=80% | SQS001"
        - "HS007:단일가격 확정 | SPRC001:step_2 ATR추정"
      violation_action: "근거 컬럼 무효. validation_status=MANUAL_CHECK_REQUIRED로 강등. 서술형 이유 삭제 후 재산출."
    prohibited_headers: ["이번 주 결론", "현재 포트폴리오 핵심 진단", "보유 종목별 운용 지침", "종합 의견"]
    failure_rule: "필수 표 누락 또는 임의 헤더 우선 출력 시 validation_status=MANUAL_CHECK_REQUIRED로 낮추고 주문표는 산출금지 사유만 출력한다."
  terminology_control:
    purpose: "기계 검증을 깨는 임의 주문구분·모드·조치유형 표현을 차단한다."
    canonical_order_type_values: ["BUY", "SELL", "STOP_LOSS", "TAKE_PROFIT", "TRAILING_STOP", "HOLD", "WATCH"]
    canonical_mode_values: ["lead", "lag", "hybrid", "none"]
    canonical_portfolio_action_values: ["BUY", "HOLD", "SELL", "TRIM", "ROTATE", "AVOID", "WATCH", "INSUFFICIENT_DATA"]
    prohibited_freeform_terms:
      - {term: "부분감액", replacement: "TRIM 또는 SELL + 정수 수량", reason: "schema enum 밖 임의 조치유형"}
      - {term: "1차 감액", replacement: "TRIM 또는 SELL + 정수 수량 + 실행근거", reason: "단계명과 주문구분 혼용"}
      - {term: "부분정리", replacement: "TRIM 또는 SELL + 정수 수량", reason: "schema enum 밖 임의 조치유형"}
      - {term: "전량", replacement: "SELL + 확인된 현재보유수량과 동일한 정수 수량", reason: "모드가 아니며 보유수량 검산 없이는 사용할 수 없음"}
      - {term: "전량매도", replacement: "SELL + 확인된 현재보유수량과 동일한 정수 수량", reason: "주문구분과 수량 검산을 분리해야 함"}
    rule: "위 표현은 모드·주문구분·조치유형 컬럼에 절대 쓰지 않는다. 필요한 경우 근거 컬럼에서만 검증된 정수 수량과 함께 설명한다."
  execution_guardrail:
    order_quantity_4stage_gate:
      stage_1: {name: "캡처 판독 원장", check: "capture_read_ledger 모든 계좌 분류 완료", fail: "CAPTURE_READ_FAILED 항목 있으면 해당 계좌 전체 주문수량 보류"}
      stage_2: {name: "계좌별 현금 검산", check: "매수 주문금액 합산 <= 주문가능현금 확인값", fail: "현금 확인값 없으면 매수금액 산출 금지"}
      stage_3: {name: "보유수량 검산", check: "매도수량 <= 확인된 보유수량", fail: "보유수량 미확인이면 매도수량 '미산출' 표시"}
      stage_4: {name: "미체결 주문 검산", check: "동일 계좌·종목 미체결 주문 여부 확인", fail: "'중복주문 방지 검산 불가' 표시 후 수동 확인 요청"}
      final_order_table_columns: ["계좌", "종목명", "현재보유수량", "평단", "현재가", "주문구분(매수/매도/손절/익절)", "지정가(원)", "수량(주)", "손절가(원)", "손절수량(주)", "익절가(원)", "익절수량(주)", "주문금액(원)", "실행후현금비중(%)", "검산_통과여부"]
      prohibition: ["4단계 검산 통과여부 없이 '제안 검토' 표기 금지", "보유수량 미확인 종목에 매도수량 숫자 기재 금지", "현금 미확인 상태에서 매수금액 합산 산출 금지"]
    order_status_precision:
      prohibited_expressions:
        - {표현: "보유 0주", 이유: "실제 보유수량 없다는 뜻으로 오인", 대체: "추가매수 0주 / 기존 보유수량 판독 필요 / 매도수량 미산출"}
        - {표현: "감액 준비 DATA_MISSING", 이유: "판독실패·미제공·계산불가 미구분", 대체: "축소 후보 — [판독_상태] 표기 후 보유수량·평단 확인 시 수량 재산출"}
        - {표현: "신규매수 0주 (현금 미확인)", 이유: "현금 없음과 진입조건 미충족 혼동", 대체: "잔고 판독 미완료로 신규매수 보류 / 또는 진입조건 미충족으로 0주"}
      gate_fail_table_columns: ["계좌", "종목명", "주문판정", "수량계산여부", "미통과단계", "다음확인사항"]

  buy_proposal_template:
    principle: >
      매수 제안은 선행형과 후행형으로 분리한다.
      두 방식 모두 손절가·손절수량·익절가·익절수량을 반드시 세트로 제시해야 하며,
      한 항목이라도 누락되면 매수 제안으로 인정하지 않는다.
    lead_mode:
      purpose: "작은 초기 포지션으로 기회를 선점하는 선행형 제안"
      _conditions: "→ entry_timing_guardrails.timing_mode_policy.lead_when (regime·required·size_rule·prohibition)"
      output_columns: ["계좌", "종목명", "주문구분", "지정가(원)", "수량(주)", "손절가(원)", "손절수량(주)", "익절가(원)", "익절수량(주)", "근거", "모드"]
    lag_mode:
      purpose: "확인 후 진입하거나 손실 축소를 위한 후행형 제안"
      _conditions: "→ entry_timing_guardrails.timing_mode_policy.lag_when (regime·required·size_rule·prohibition)"
      output_columns: "→ lead_mode.output_columns 동일"
    hybrid_mode:
      purpose: "애매한 장세에서 선행형과 후행형을 분리해 혼합 사용"
      rule: "시범진입은 선행형, 본진입·축소는 후행형으로 분리"
      mandatory_note: "보고서에는 반드시 선행형/후행형 중 어느 모드인지 표시"
    validation:
      required_for_any_buy:
        - "손절가(원)"
        - "손절수량(주)"
        - "익절가(원)"
        - "익절수량(주)"
      no_set_no_buy: "4개 중 1개라도 누락되면 매수 제안 금지"

  _report_templates: "_file: RetirementAssetPortfolioReportTemplate.yaml (data_flow·current_holdings·market_leader·scenario·rebalancing 양식) — 메인 manifest load_sequence.STEP_3_for_output 참조"

  unified_example_row_set:  # [R6] 전 섹션 공통 참조 예시 데이터 — 중복 분산 제거
    purpose: "stop_loss·take_profit·buy_proposal·sell_proposal output_examples의 단일 정규 참조 집합"
    columns:
      buy: ["계좌", "종목명", "주문구분", "모드", "지정가(원)", "수량(주)", "손절가(원)", "손절수량(주)", "익절가(원)", "익절수량(주)", "근거"]
      sell: ["계좌", "종목명", "주문구분", "지정가(원)", "수량(주)", "매도사유", "근거"]
      stop: ["계좌", "종목명", "주문구분", "지정가(원)", "수량(주)", "손절가(원)", "손절수량(주)", "근거"]
      take: ["계좌", "종목명", "주문구분", "지정가(원)", "수량(주)", "익절가(원)", "익절수량(주)", "근거"]
      trailing: ["계좌", "종목명", "주문구분", "지정가(원)", "수량(주)", "트레일링기준가(원)", "잔여수량(주)", "근거"]
    rows:
      buy_lead:    {계좌: "ISA", 주문구분: "매수", 모드: "lead", 지정가: 12500, 수량: 80, 손절가: 11800, 손절수량: 80, 익절가: 14500, 익절수량: 40, 산출공식_ID: "POSITION_SIZE_V1", 근거: "risk_on + Expected_Edge>=1.8"}
      buy_lag:     {계좌: "일반계좌", 주문구분: "매수", 모드: "lag", 지정가: 24800, 수량: 120, 손절가: 23200, 손절수량: 120, 익절가: 27500, 익절수량: 60, 산출공식_ID: "POSITION_SIZE_V1", 근거: "neutral + 수급 유지"}
      buy_hybrid:  {계좌: "연금저축", 주문구분: "매수", 모드: "hybrid", 지정가: 38000, 수량: 50, 손절가: 36000, 손절수량: 50, 익절가: 42000, 익절수량: 25, 산출공식_ID: "POSITION_SIZE_V1", 근거: "시범진입 후 확인"}
      sell:        {계좌: "일반계좌", 주문구분: "매도", 지정가: 24800, 수량: 60, 매도사유: "후행 정리", 산출공식_ID: "N/A", 근거: "20일선 이탈 + 거래대금 감소"}
      stop_loss:   {계좌: "ISA", 주문구분: "손절", 지정가: 23200, 수량: 100, 손절가: 23200, 손절수량: 100, 산출공식_ID: "STOP_PRICE_CORE_V1", 근거: "ATR20 이탈 + 수급 이탈"}
      take_profit: {계좌: "연금저축", 주문구분: "익절", 지정가: 14500, 수량: 40, 익절가: 14500, 익절수량: 40, 산출공식_ID: "TAKE_PROFIT_LADDER_V2", 근거: "tier_1 + 수급 유지"}
      trailing:    {계좌: "연금저축", 주문구분: "익절", 지정가: 0, 수량: 30, 트레일링기준가: 42000, 잔여수량: 30, 산출공식_ID: "TRAILING_STOP_PRICE_V1", 근거: "PROFIT_LOCK_RATCHET_V1:tier_2완료 → TRAILING_STOP_PRICE_V1"}
  buy_proposal_output_examples:
    purpose: "매수 제안은 선행형/후행형/혼합형 중 하나로만 출력하고, 표기 모드를 보고서에 명시한다."
    _examples: "→ unified_example_row_set.rows.buy_lead · buy_lag · buy_hybrid 참조"
    prohibition:
      - "모드 표기 없이 매수 제안 금지"
      - "손절가·손절수량·익절가·익절수량 중 하나라도 누락된 표는 무효"
      - "선행형 예시를 후행형 근거로, 후행형 예시를 선행형 근거로 혼용 금지"
  sell_proposal_output_examples:
    purpose: "매도·손절·익절은 모두 가격과 수량 세트를 포함한 표로만 출력한다."
    _examples: "→ unified_example_row_set.rows.sell · stop_loss · take_profit 참조"
    prohibition:
      - "매도·손절·익절 중 가격 또는 수량 하나라도 누락된 표는 무효"
      - "매도 예시를 손절 예시로, 손절 예시를 익절 예시로 혼용 금지"
      - "후행 손절을 선행 진입 근거로 사용 금지"

  unified_order_sheet_example:
    purpose: "매수/매도/손절/익절을 한 장에서 비교하는 최종 통합 표 예시"
    columns: ["계좌", "종목명", "현재보유수량", "평단", "현재가", "주문구분", "모드", "지정가(원)", "수량(주)", "손절가(원)", "손절수량(주)", "익절가(원)", "익절수량(주)", "주문금액(원)", "산출공식_ID", "근거", "검산상태"]
    _rows: "→ unified_example_row_set.rows (buy_lead·buy_lag·sell·stop_loss·take_profit 참조)"
    prohibition:
      - "한 장의 통합 표라도 가격 또는 수량 누락 시 무효"
      - "매수/매도/손절/익절 모드 혼용 시 모드 표기를 누락하지 않는다"
      - "0으로 적는 칸은 실제 0주 또는 해당 없음의 명시적 표현일 때만 허용"

  immediate_execution_playbook:
    purpose: "HTS에 옮길지 말지 판단하는 최종 제안 표준. 보고서 상단에 1회만 출력."
    rule: >
      제안 검토 표는 unified_order_sheet_example을 우선 사용한다.
      각 행은 가격과 수량이 반드시 짝으로 있어야 하며, 선행형/후행형/혼합형 모드를 반드시 표기한다.
      선행형은 작은 시범진입만, 후행형은 확인 후 진입·축소만 허용한다.
      에이전트는 지정가/손절가/익절가 산출 시 반드시 [산출공식_ID]를 기재해야 하며, 명세(spec/13_formula_registry.yaml)의 
      공식 산출값이 아닌 차트 지지선 등을 핑계로 가격을 임의 조정(할루시네이션)하는 것을 절대 금지한다.
    columns: ["계좌", "종목명", "현재보유수량", "평단", "현재가", "주문구분", "모드", "지정가(원)", "수량(주)", "손절가(원)", "손절수량(주)", "익절가(원)", "익절수량(주)", "주문금액(원)", "산출공식_ID", "실행근거", "검산상태"]
    _example_rows: "→ unified_example_row_set.rows 참조 (산출공식_ID 및 검산상태=PASS 추가)"
    reason_column_format:
      rule: "실행근거 컬럼은 [공식ID 또는 Rule_ID]:[산출값 또는 조건결과] 형식만 허용. 서술형 이유로 규칙을 우회하거나 면제하는 행위 절대 금지."
      compliant_examples:
        - "STOP_PRICE_CORE_V1:23,200원 | ATR20=640"
        - "TAKE_PROFIT_LADDER_V2:tier_1=14,500원 | 수급 유지"
        - "RW_EXIT:합계4 | 청산비율=80%"
        - "P4_no_intraday_speculation:장중캡처 → TRIM만 허용"
      non_compliant_examples:
        - "200,000원은 심리적 지지선이라 손절 불필요"
        - "K2 수주 모멘텀이 있어서 전량 매도 안 함"
        - "현금 14% 달성으로 추가 매도 불필요"
        - "시장 상황 감안하여 손절 보류"
    prohibition:
      - "검산상태가 PASS가 아니면 제안 검토 표 금지"
      - "매도·손절·익절 행에서 현재보유수량·평단·현재가가 비어 있으면 PASS 금지"
      - "가격과 수량이 모두 채워지지 않으면 주문 불가"
      - "선행형/후행형/혼합형 모드 중 하나라도 비어 있으면 무효"
      - "산출공식_ID가 누락되거나, 공식 산출값이 아닌 임의로 창작한 가격 사용 절대 금지"
      - "조건부 주문 시 '00원 돌파 실패 시'와 같은 모호한 HTS 입력 불가 조건을 금지하고 오직 단일 이탈 가격만 명시한다."
      - "실행근거 컬럼에 서술형 이유로 규칙 면제·유보를 정당화하는 내용 기재 금지. Rule_ID+산출값 형식 외 텍스트는 violation_action 적용."

    concise_hts_input_sheet:
      purpose: "보고서 첫 화면에 붙는 초간단 HTS 입력용 요약표. 입력 필드만 남겨 혼선을 줄이고, 우선순위·기준시점(종가/장중)을 함께 고정한다."
    rule: >
      이 표는 제안 검토 표에서 파생된 축약판이다.
      각 행은 가격과 수량을 반드시 함께 가지며, 손절·익절은 양쪽 모두 수량을 포함해야 한다.
      모드가 비어 있으면 출력하지 않는다.
    columns: ["우선순위그룹", "우선순위", "계좌", "종목명", "주문구분", "모드", "지정가(원)", "기준시점(종가/장중)", "수량(주)", "수량기준", "손절가(원)", "손절수량(주)", "익절가(원)", "익절수량(주)"]
    _example_rows: "→ unified_example_row_set.rows 참조"
    prohibition:
      - "한 칸이라도 비면 초간단 요약표 출력 금지"
      - "모드 없는 행 출력 금지"
      - "0은 실제 0주 또는 해당 없음으로 명시 가능한 경우에만 허용"

  rebalancing_report_template:
    _file: "RetirementAssetPortfolioReportTemplate.yaml"
    _note: "activation·columns·example_rows·prohibition → 보고서양식.yaml 참조 (메인 manifest load_sequence.STEP_3_for_output)"

  market_context_learning_note:
    _file: "RetirementAssetPortfolioReportTemplate.yaml"
    _note: "거시·미시 시장상황, 투자자 고민 포인트, 용어, 판단근거를 설명하는 조건부 학습 블록. 주문 산출과 validation_status를 대체하지 않는다."

  sell_priority_decision_table:
    _file: "RetirementAssetPortfolioReportTemplate.yaml"
    _note: "여러 매도 후보 간 실행 우선순위를 정하는 조건부 표. canonical_ref는 portfolio_exposure_framework.sell_priority_engine이며, 보고서 렌더링은 regime_adjusted_sell_priority_json.final_regime_rank 우선 적용."

  decision_trace_table:
    _file: "RetirementAssetPortfolioReportTemplate.yaml"
    _note: "상태 머신의 각 판단 단계와 적용 rule_id를 남기는 필수 추적 표. 판단 재현성을 위해 HTS 표보다 먼저 출력."

  report_header_rule:
    purpose: "보고서 헤더는 등급과 display_policy를 기준으로 어떤 표를 먼저 보여줄지 고정한다."
    header_order:
      _canonical: "→ recommendation_grade.display_policy.output_sequence 참조 (step_1~step_15)"
      _routing: "외부 파일(보고서양식.yaml) 항목: step_3·step_5·step_6·step_9"
    note: "헤더 순서와 display_policy가 충돌하면 display_policy를 우선한다."
    compact_header_titles:
      capture_read_ledger: "판독 원장"
      data_completeness_matrix: "데이터 완성도"
      order_quantity_4stage_gate: "주문 검산"
      decision_trace_table: "판단 추적"
      recommendation_grade: "등급"
      sell_priority_decision_table: "매도 우선순위"
      concise_hts_input_sheet: "HTS 요약"
      immediate_execution_playbook: "제안 검토"
      market_leader_screening_report_template: "주도주 후보"
      current_holdings_analysis_report_template: "보유주 진단"
      market_micro_macro_flow_scenario_report_template: "미시·거시·흐름"
      market_context_learning_note: "학습 해설"
      buy_proposal_output_examples: "매수 예시"
      sell_proposal_output_examples: "매도 예시"
      unified_order_sheet_example: "통합 주문표"
      data_flow_analysis_report: "데이터 흐름"
      rebalancing_report_template: "리밸런싱"
    compact_title_rule: "상단 헤더는 위 축약 제목을 사용하고, 본문 표명은 원문 키를 유지한다."

performance_evidence:
  trade_journal_required: true
  record_fields: ["recommendation_id", "signal_date", "account", "ticker", "entry_price", "quantity", "stop_price", "target_or_trailing_rule", "fees_tax_slippage_krw", "exit_price", "exit_reason", "net_return_pct", "holding_days", "max_adverse_excursion_pct"]
  benchmark: {primary: "KOSPI", secondary: "KOSDAQ 또는 해당 섹터 ETF", evaluation: "동일 보유기간 기준 세후·비용차감 초과수익률"}
  trade_journal_format:
    columns: ["종목명", "진입일", "청산일", "보유일수", "진입가", "청산가", "수량", "세금수수료", "실질수익률(Net%)", "초과수익(vs KOSPI)"]
    rule: "모든 청산(익절/손절) 거래는 반드시 이 장부 포맷으로 기록하여 실적으로 증빙한다."
  validation_window: {minimum_trades: 20, preferred_trades: 30}
  pass_fail:
    net_return_formula: "Net_Return_Pct = ((Exit_Price - Entry_Price) / Entry_Price) * 100 - Total_Tax_Fee_Pct - Slippage_Pct"
    keep_rule: "net_expectancy > 0, benchmark_excess_return > 0, max_drawdown <= 사전한도"
    downgrade_rule: "최근 20건 기준 net_expectancy <= 0 또는 benchmark 대비 -5%p 열위이면 A등급 산출 금지"
    retire_rule: "동일 규칙 30건 후 비용차감 기대값 <= 0이면 해당 신호 폐기"
  core_satellite_alpha_audit:
    alias_of: "alpha_audit"
    decision_rule:  # [P136] 35~50% 구간 caution 추가 — 공백 해소
      keep:
        condition: "hit_rate_20d >= 50% AND alpha_after_cost_pct 평균 > 0"
        action: "정상 운영"
      caution:
        condition: "35% <= hit_rate_20d < 50%"
        action: "신규 core_satellite 최대 2개 제한. 진입 안전마진 +1%p 하향. 다음 10건 후 재평가."
      hit_rate_penalty:
        condition: "hit_rate_20d < 35%"
        action: "신규 core_satellite 최대 1개 제한. 진입 안전마진 +2%p 하향."
      reduce:
        condition: "alpha_after_cost_pct 평균 <= 0 OR MAE -8% 이하 발생률 25% 초과"
        action: "core_satellite 총한도 7%에서 3%로 축소"
      suspend:
        condition: "최근 30건 alpha_after_cost_pct 평균 <= -3%p"
        action: "core_satellite 신규매수 중단. 코어/현금/ETF 중심 회귀."
      priority: "suspend > reduce > hit_rate_penalty > caution > keep (복합 조건 시 더 제한적 규칙 우선)"
    reporting_rule: ["core_satellite 신규매수 제안 전 core_satellite_alpha_audit 상태를 PASS/REDUCE/SUSPEND 중 하나로 표시", "core_satellite_alpha_audit 미작성 시 후보 최대 B-조건부"]
