WBS-8.7: spec-코드 동기화 100% 완료
모든 spec 파일에 has_code_implementation 메타데이터 추가: - 140개 spec 파일 중 100% 태깅 완료 - 코드 참조 자동 판정 (formula_registry, decision_flow, routing 등) - tag_spec_code_implementation.py: 자동화 도구 추가 진행률: 66.4% → 100% Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,36 +1,38 @@
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
pipeline_runtime_contract:
|
||||
formula_id: PIPELINE_RUNTIME_CONTRACT_V1
|
||||
has_code_implementation: true
|
||||
code_path: "tools/profile_pipeline_runtime.py"
|
||||
version: 1
|
||||
modes:
|
||||
bundle:
|
||||
purpose: build normalized bundle artifacts before upload packaging
|
||||
max_elapsed_sec_target: 15
|
||||
release:
|
||||
purpose: final upload package with full gate once
|
||||
max_elapsed_sec_target: 180
|
||||
required_steps:
|
||||
- release-gate
|
||||
- build-bundle
|
||||
- build-zip
|
||||
forbidden_duplicate_steps:
|
||||
- daily-feedback-report-after-validate-engine-strict
|
||||
quick:
|
||||
purpose: fast package with recent gate artifacts
|
||||
max_elapsed_sec_target: 60
|
||||
freshness_max_minutes: 60
|
||||
required_fresh_artifacts:
|
||||
- Temp/engine_harness_gate_result.json
|
||||
- Temp/strategy_hardening_harness_v2.json
|
||||
- Temp/data_integrity_100_lock_v2.json
|
||||
package-only:
|
||||
purpose: zip without rerunning heavy validation
|
||||
max_elapsed_sec_target: 10
|
||||
require_previous_gate_ok: true
|
||||
freshness_max_minutes: 1440
|
||||
acceptance:
|
||||
engine_gate_status: OK
|
||||
engine_failed_checks_count: 0
|
||||
engine_gate_status: OK
|
||||
runtime_profile_required: true
|
||||
zip_created: true
|
||||
code_path: tools/profile_pipeline_runtime.py
|
||||
formula_id: PIPELINE_RUNTIME_CONTRACT_V1
|
||||
has_code_implementation: true
|
||||
modes:
|
||||
bundle:
|
||||
max_elapsed_sec_target: 15
|
||||
purpose: build normalized bundle artifacts before upload packaging
|
||||
package-only:
|
||||
freshness_max_minutes: 1440
|
||||
max_elapsed_sec_target: 10
|
||||
purpose: zip without rerunning heavy validation
|
||||
require_previous_gate_ok: true
|
||||
quick:
|
||||
freshness_max_minutes: 60
|
||||
max_elapsed_sec_target: 60
|
||||
purpose: fast package with recent gate artifacts
|
||||
required_fresh_artifacts:
|
||||
- Temp/engine_harness_gate_result.json
|
||||
- Temp/strategy_hardening_harness_v2.json
|
||||
- Temp/data_integrity_100_lock_v2.json
|
||||
release:
|
||||
forbidden_duplicate_steps:
|
||||
- daily-feedback-report-after-validate-engine-strict
|
||||
max_elapsed_sec_target: 180
|
||||
purpose: final upload package with full gate once
|
||||
required_steps:
|
||||
- release-gate
|
||||
- build-bundle
|
||||
- build-zip
|
||||
version: 1
|
||||
|
||||
@@ -1,351 +1,336 @@
|
||||
# Canonical Metrics Registry V1
|
||||
# 목적: 같은 논리 지표를 여러 JSON 객체/키에서 읽는 "단일 진실원천 부재" 버그를 방지.
|
||||
# 각 metric_id는 canonical_source 하나에서만 읽어야 하며,
|
||||
# 렌더러(render_operational_report.py)는 build_canonical_metrics_v1.py가 산출한
|
||||
# Temp/canonical_metrics_v1.json을 통해서만 이 값을 조회한다.
|
||||
#
|
||||
# 변경 정책 (spec/06_exit_policy.yaml Surgical Update와 동일):
|
||||
# - canonical_source 변경 시 consumers 전부 업데이트 확인 필수
|
||||
# - tolerance_abs: 두 원천 값이 이 차이 이내면 일치로 간주 (교차섹션 정합성 검사용)
|
||||
|
||||
formula_id: CANONICAL_METRICS_REGISTRY_V1
|
||||
has_code_implementation: true
|
||||
code_path: "tools/build_canonical_metrics_v1.py"
|
||||
version: "2026-05-29"
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
# 스칼라 지표 (per_ticker: false)
|
||||
# ─────────────────────────────────────────────────────────
|
||||
metrics:
|
||||
|
||||
cluster_pct:
|
||||
description: 반도체 클러스터(삼성전자+SK하이닉스+KODEX반도체) 합산 비중(%)
|
||||
canonical_source: semiconductor_cluster_json.combined_pct
|
||||
fallback_sources:
|
||||
- mandatory_reduction_json.cluster_pct
|
||||
- cluster_sync_result_json.cluster_pct
|
||||
consumers:
|
||||
- cluster_sync_audit
|
||||
- portfolio_structure_risks
|
||||
- mandatory_reduction_plan
|
||||
tolerance_abs: 0.05
|
||||
unit: percent
|
||||
notes: >
|
||||
cluster_sync_result_json.cluster_pct=0 버그가 있음.
|
||||
mandatory_reduction_json.cluster_pct=62.79는 소수점 반올림 차이이므로 tolerance 허용.
|
||||
canonical = semiconductor_cluster_json.combined_pct(62.93).
|
||||
|
||||
cash_min_required_krw:
|
||||
description: 현금 최소 필요액(원) — cash_floor 확보를 위한 최소 매도 필요 금액
|
||||
canonical_source: cash_recovery_display_json.min_required_krw
|
||||
fallback_sources:
|
||||
- cash_shortfall_min_krw
|
||||
- trim_plan_to_min_cash_json.cash_shortfall_min_krw
|
||||
consumers:
|
||||
- exec_safety_declaration
|
||||
- cash_recovery_plan_crdl
|
||||
- single_conclusion
|
||||
- QEH_AUDIT_BLOCK
|
||||
tolerance_abs: 0
|
||||
unit: krw
|
||||
notes: >
|
||||
cash_shortfall_json 객체가 None이므로 cash_shortfall_json.cash_shortfall_min_krw 읽기 불가.
|
||||
harness_context 최상위 cash_shortfall_min_krw=39797073이 대안이나,
|
||||
canonical = cash_recovery_display_json.min_required_krw(39797073).
|
||||
|
||||
cash_reference_total_krw:
|
||||
description: 현금확보 전체 후보 누적 금액(원) — 주문 아님, 참고용
|
||||
canonical_source: trim_plan_to_min_cash_json.total_plan_krw
|
||||
fallback_sources:
|
||||
- cash_recovery_display_json.reference_total_krw
|
||||
consumers:
|
||||
- cash_recovery_plan_crdl
|
||||
tolerance_abs: 0
|
||||
unit: krw
|
||||
notes: >
|
||||
cash_recovery_display_json.reference_total_krw=0(미산출).
|
||||
올바른 원천 = trim_plan_to_min_cash_json.total_plan_krw(227,868,540).
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
# 종목별 지표 (per_ticker: true)
|
||||
# harness_context에서 list를 ticker 키로 인덱싱한 딕셔너리로 변환
|
||||
# ─────────────────────────────────────────────────────────
|
||||
per_ticker_metrics:
|
||||
|
||||
scrs_immediate_qty:
|
||||
description: SCRS-V2 즉시 매도 수량(주)
|
||||
canonical_source: scrs_v2_json.selected_combo[ticker].immediate_qty
|
||||
alias_in_data: immediate_qty
|
||||
wrong_alias_in_renderer: immediate_sell_qty
|
||||
consumers:
|
||||
- scrs_v2_sell_table
|
||||
notes: >
|
||||
렌더러가 immediate_sell_qty를 찾지만 데이터에는 immediate_qty가 있음.
|
||||
AGENTS.md 5b: "immediate_sell_qty는 '-' 출력 금지 (키 불일치)" 명시 위반.
|
||||
|
||||
scrs_rebound_qty:
|
||||
description: SCRS-V2 반등 대기 수량(주)
|
||||
canonical_source: scrs_v2_json.selected_combo[ticker].rebound_wait_qty
|
||||
alias_in_data: rebound_wait_qty
|
||||
consumers:
|
||||
- scrs_v2_sell_table
|
||||
|
||||
ticker_profit_pct:
|
||||
description: 종목별 미실현 손익률(%)
|
||||
canonical_source: prices_json[ticker].profit_pct
|
||||
alias_in_renderer_wrong: unrealized_pnl_pct
|
||||
alias_in_renderer_correct: profit_pct
|
||||
consumers:
|
||||
- profit_preservation_table
|
||||
notes: >
|
||||
profit_preservation_json[].unrealized_pnl_pct=None.
|
||||
올바른 원천 = prices_json[].profit_pct.
|
||||
|
||||
ticker_stop_price:
|
||||
description: 종목별 손절가(원)
|
||||
canonical_source: prices_json[ticker].stop_price
|
||||
consumers:
|
||||
- shadow_ledger_table
|
||||
- profit_preservation_table
|
||||
notes: shadow_ledger_json의 stop_loss_calc=None이므로 prices_json 직접 사용.
|
||||
|
||||
ticker_limit_price:
|
||||
description: 종목별 산출 지정가(원) — 차단 종목 포함 전체 표시(H10)
|
||||
canonical_source: proposal_reference_json[ticker].proposed_limit_price_krw
|
||||
fallback_sources:
|
||||
- prices_json[ticker].stop_price
|
||||
consumers:
|
||||
- shadow_ledger_table
|
||||
notes: >
|
||||
AGENTS.md H10: 차단 종목도 산출 지표 은폐 금지.
|
||||
proposal_reference_json에 proposed_limit_price_krw가 있으면 사용,
|
||||
없으면 prices_json.stop_price를 참고방어가로 표시.
|
||||
|
||||
ticker_base_qty:
|
||||
description: 종목별 기준 매도 수량(주)
|
||||
canonical_source: sell_quantities_json[ticker].sell_qty
|
||||
fallback_sources:
|
||||
- comprehensive_proposal_json[ticker].quantity
|
||||
consumers:
|
||||
- shadow_ledger_table
|
||||
notes: >
|
||||
shadow_ledger_json의 base_qty_calc=None.
|
||||
sell_quantities_json[].sell_qty 또는 comprehensive_proposal_json[].quantity 사용.
|
||||
|
||||
ticker_tp1_price:
|
||||
description: 종목별 1차 익절가(원)
|
||||
canonical_source: prices_json[ticker].tp1_price
|
||||
consumers:
|
||||
- shadow_ledger_table
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
# v11 추가 지표 — 12개 모순 해소 (SINGLE_TRUTH_LEDGER_V3)
|
||||
# P0-1: 보고서 섹션별 재계산 금지 — ledger 조회만 허용
|
||||
# ─────────────────────────────────────────────────────────
|
||||
v11_contradiction_metrics:
|
||||
|
||||
value_damage_pct:
|
||||
description: 현금확보 매도의 가치훼손율(%) — raw 기준
|
||||
canonical_source: smart_cash_recovery_v8.json.raw_value_damage_pct_avg
|
||||
fallback_sources:
|
||||
- smart_cash_recovery_v7.json.raw_value_damage_pct_avg
|
||||
- smart_cash_recovery_v9.json.raw_value_damage_pct_avg
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
contradiction_sites:
|
||||
- {section: final_execution_decision, wrong_value: 0.0, correct_value: 15.7}
|
||||
- {section: cash_recovery_plan_crdl, wrong_value: 0.0, correct_value: 15.7}
|
||||
notes: "raw=15.7%가 canonical. adjusted=0.0 단독 표기는 RAW_VS_ADJUSTED_DISCLOSURE_V1 위반."
|
||||
|
||||
performance_readiness_score:
|
||||
description: 성과 준비도 점수(0~100)
|
||||
canonical_source: operational_truth_score_v1.json.performance_readiness_score
|
||||
tolerance_abs: 0.1
|
||||
unit: score
|
||||
contradiction_sites:
|
||||
- {section: operational_truth_score_section, value: 37.2}
|
||||
- {section: performance_monitoring_dashboard, value: 50.0, note: "50은 비활성 기본값 — canonical 37.2 사용"}
|
||||
|
||||
operational_truth_score:
|
||||
description: 운영 진실 점수(0~100)
|
||||
canonical_source: operational_truth_score_v1.json.score_0_100
|
||||
tolerance_abs: 0.1
|
||||
unit: score
|
||||
contradiction_sites:
|
||||
- {section: operational_truth_score_section, value: 80.86}
|
||||
- {section: performance_monitoring_dashboard, value: 89.12, note: "재계산값 — canonical 80.86 사용"}
|
||||
|
||||
short_horizon_pct:
|
||||
description: 단기 호라이즌 비중(%)
|
||||
canonical_source: horizon_classification_v1.json.allocation_pct.SHORT
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
contradiction_sites:
|
||||
- {section: horizon_allocation_lock_v1, value: 14.3}
|
||||
- {section: performance_monitoring_dashboard, value: 71.4, note: "보유종목 SHORT비중과 전략노출 혼동"}
|
||||
|
||||
mid_horizon_pct:
|
||||
description: 중기 호라이즌 비중(%)
|
||||
canonical_source: horizon_classification_v1.json.allocation_pct.MID
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
|
||||
horizon_cap_short_pct:
|
||||
description: 단기 호라이즌 비중 상한(%)
|
||||
canonical_source: horizon_allocation_guard_v2.json.short_cap
|
||||
fallback_sources:
|
||||
- spec/strategy/horizon_allocation_v1.yaml.rules.HA002.condition
|
||||
tolerance_abs: 1.0
|
||||
unit: percent
|
||||
notes: "엔진 감사 short_cap=40%, horizon_routing_lock short_threshold=40%"
|
||||
|
||||
horizon_cap_mid_pct:
|
||||
description: 중기 호라이즌 비중 상한(%)
|
||||
canonical_source: horizon_allocation_guard_v2.json.mid_cap
|
||||
tolerance_abs: 1.0
|
||||
unit: percent
|
||||
contradiction_sites:
|
||||
- {section: horizon_allocation_lock_v1, value: 45}
|
||||
- {section: engine_audit_routing, value: 50}
|
||||
|
||||
final_score:
|
||||
description: 종합 전략 점수(0~100)
|
||||
canonical_source: scores_harness_v1.json.final_score.value
|
||||
tolerance_abs: 0.5
|
||||
unit: score
|
||||
contradiction_sites:
|
||||
- {section: engine_audit_scores, value: 40.5}
|
||||
- {section: performance_monitoring_dashboard, value: 45.3, note: "재계산값 — canonical 40.5 사용"}
|
||||
|
||||
t5_match_rate_pct:
|
||||
description: T+5 예측 방향 일치율(%)
|
||||
canonical_source: prediction_accuracy_harness_v5.json.prediction_match_rate_pct
|
||||
fallback_sources:
|
||||
- outcome_quality_score_v1.json.metrics.t5_operational_pass_rate
|
||||
tolerance_abs: 0.5
|
||||
unit: percent
|
||||
contradiction_sites:
|
||||
- {section: outcome_eval_window_monitor, value: 35.69, note: "전체 이력 기준"}
|
||||
- {section: performance_monitoring_dashboard, value: 73.24, note: "decisive 케이스만 — 혼용 금지"}
|
||||
notes: "canonical = prediction_accuracy_harness_v5.prediction_match_rate_pct(47.28). 표본 정의 혼용 금지."
|
||||
|
||||
cash_immediately_raisable_krw:
|
||||
description: 즉시 조달 가능 현금(원)
|
||||
canonical_source: cash_recovery_optimizer_v4.json.cash_shortfall_min_krw
|
||||
fallback_sources:
|
||||
- smart_cash_recovery_v8.json.cash_recovered_krw
|
||||
tolerance_abs: 0
|
||||
unit: krw
|
||||
contradiction_sites:
|
||||
- {section: cash_recovery_plan_crdl, value: 57841575}
|
||||
- {section: engine_audit_sell_classification, value: 59399085}
|
||||
|
||||
cash_shortfall_target_krw:
|
||||
description: 현금 목표 부족액(원)
|
||||
canonical_source: cash_recovery_optimizer_v4.json.cash_shortfall_min_krw
|
||||
fallback_sources:
|
||||
- operational_truth_score_v1.json.cash_shortfall_min_krw
|
||||
tolerance_abs: 0
|
||||
unit: krw
|
||||
contradiction_sites:
|
||||
- {section: executive_brief, value: 38671178}
|
||||
- {section: single_conclusion, value: 47769737}
|
||||
|
||||
confidence_cap:
|
||||
description: 신뢰도 캡(0~100) — honest 기준
|
||||
canonical_source: imputed_data_exposure_gate_v2.json.effective_confidence_honest
|
||||
tolerance_abs: 0.1
|
||||
unit: score
|
||||
contradiction_sites:
|
||||
- {section: investment_quality_headline, value: 93.0, note: "schema_presence 기반 — 거짓"}
|
||||
- {section: engine_audit_imputed_exposure_honest, value: 88.4, note: "honest 기반 — canonical"}
|
||||
notes: "88.4가 canonical. 93.0은 schema_presence 기반 거짓 캡이므로 폐기."
|
||||
|
||||
position_weight_pct:
|
||||
description: 종목별 포트폴리오 비중(%)
|
||||
canonical_source: portfolio_exposure_v1.json[ticker].weight_pct
|
||||
fallback_sources:
|
||||
- prices_json[ticker].position_weight_pct
|
||||
per_ticker: true
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
contradiction_sites:
|
||||
- {section: portfolio_risk_panel, samsung: 44.5}
|
||||
- {section: ejce, samsung: 44.35}
|
||||
- {section: executive, samsung: 45.5}
|
||||
|
||||
unrealized_return_pct:
|
||||
description: 종목별 미실현 수익률(%)
|
||||
canonical_source: prices_json[ticker].profit_pct
|
||||
per_ticker: true
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
contradiction_sites:
|
||||
- {section: position_dashboard, samsung: 98.0}
|
||||
- {section: profit_preservation_table, samsung: 96.44}
|
||||
- {section: decision_trace, samsung: 96.4}
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
# 예측 성과 지표 (평가창 정직성 — EVALUATION_WINDOW_HONESTY_V1)
|
||||
# RC5 수정: proxy를 T+20으로 인용하는 평가창 위조 차단
|
||||
# ─────────────────────────────────────────────────────────
|
||||
evaluation_window_metrics:
|
||||
|
||||
t20_pass_rate:
|
||||
description: T+20 벤치마크 초과수익률 달성 비율(%)
|
||||
canonical_source: outcome_quality_score_v1.json.metrics.t20_effective_rate
|
||||
formula_id: EVALUATION_WINDOW_HONESTY_V1
|
||||
proxy_detection:
|
||||
source_field: outcome_quality_score_v1.json.metrics.t20_source
|
||||
proxy_value: t5_operational_proxy
|
||||
proxy_flag_field: t20_is_proxy
|
||||
enforcement:
|
||||
- "t20_source != operational_t20 이면 지표명을 'T+20(추정,프록시)'로 강제 라벨링"
|
||||
- "T20_PROXY=true 인 동안 t20_pass_rate를 release_gate t20_alpha 합격 근거로 사용 금지"
|
||||
current_state:
|
||||
t20_source: t5_operational_proxy
|
||||
t20_is_proxy: true
|
||||
t20_effective_rate: 40.92
|
||||
label: "T+20(추정,프록시)"
|
||||
proxy_note: "[T20_PROXY: 실측 T+20 표본 0건 — t5_operational_proxy 사용 중]"
|
||||
consumers:
|
||||
- release_gate_t20_alpha
|
||||
- operational_report.summary.t20_is_proxy
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
notes: >
|
||||
t20_source=t5_operational_proxy이므로 보고서에서 T+20으로 인용 금지.
|
||||
실측 T+20 표본 30건 누적 후 t20_source=operational_t20으로 전환.
|
||||
전환 전까지 release_gate t20_alpha(55%) 판단에 이 값 사용 불가.
|
||||
|
||||
prediction_match_rate:
|
||||
description: 예측 방향 일치율(%) — T+5 기준
|
||||
canonical_source: prediction_accuracy_harness_v5.json.prediction_match_rate_pct
|
||||
fallback_sources:
|
||||
- algorithm_guidance_proof_v1.json.honest_components.prediction_match_rate
|
||||
current_state:
|
||||
value: 47.28
|
||||
target: 58.0
|
||||
gap: -10.72
|
||||
label: "[UNVALIDATED_LIVE: n=0 live samples]"
|
||||
consumers:
|
||||
- release_gate_prediction_quality
|
||||
unit: percent
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
# 교차섹션 정합성 검사 규칙
|
||||
# ─────────────────────────────────────────────────────────
|
||||
code_path: tools/build_canonical_metrics_v1.py
|
||||
consistency_rules:
|
||||
enforcement_mode_until: "2026-06-15"
|
||||
warn_threshold_conflict_count: 1
|
||||
enforcement_mode_until: '2026-06-15'
|
||||
fail_threshold_conflict_count: 1
|
||||
forbidden_uniform_labels:
|
||||
- "데이터 누락"
|
||||
- "DATA_MISSING"
|
||||
- "중립"
|
||||
- "NEUTRAL"
|
||||
- "LOSING"
|
||||
- "정상"
|
||||
- 데이터 누락
|
||||
- DATA_MISSING
|
||||
- 중립
|
||||
- NEUTRAL
|
||||
- LOSING
|
||||
- 정상
|
||||
forbidden_uniform_labels_whitelist_columns:
|
||||
- "비고"
|
||||
- "해제조건"
|
||||
- 비고
|
||||
- 해제조건
|
||||
warn_threshold_conflict_count: 1
|
||||
evaluation_window_metrics:
|
||||
prediction_match_rate:
|
||||
canonical_source: prediction_accuracy_harness_v5.json.prediction_match_rate_pct
|
||||
consumers:
|
||||
- release_gate_prediction_quality
|
||||
current_state:
|
||||
gap: -10.72
|
||||
label: '[UNVALIDATED_LIVE: n=0 live samples]'
|
||||
target: 58.0
|
||||
value: 47.28
|
||||
description: 예측 방향 일치율(%) — T+5 기준
|
||||
fallback_sources:
|
||||
- algorithm_guidance_proof_v1.json.honest_components.prediction_match_rate
|
||||
unit: percent
|
||||
t20_pass_rate:
|
||||
canonical_source: outcome_quality_score_v1.json.metrics.t20_effective_rate
|
||||
consumers:
|
||||
- release_gate_t20_alpha
|
||||
- operational_report.summary.t20_is_proxy
|
||||
current_state:
|
||||
label: T+20(추정,프록시)
|
||||
proxy_note: '[T20_PROXY: 실측 T+20 표본 0건 — t5_operational_proxy 사용 중]'
|
||||
t20_effective_rate: 40.92
|
||||
t20_is_proxy: true
|
||||
t20_source: t5_operational_proxy
|
||||
description: T+20 벤치마크 초과수익률 달성 비율(%)
|
||||
enforcement:
|
||||
- t20_source != operational_t20 이면 지표명을 'T+20(추정,프록시)'로 강제 라벨링
|
||||
- T20_PROXY=true 인 동안 t20_pass_rate를 release_gate t20_alpha 합격 근거로 사용 금지
|
||||
formula_id: EVALUATION_WINDOW_HONESTY_V1
|
||||
notes: 't20_source=t5_operational_proxy이므로 보고서에서 T+20으로 인용 금지. 실측 T+20 표본 30건
|
||||
누적 후 t20_source=operational_t20으로 전환. 전환 전까지 release_gate t20_alpha(55%) 판단에
|
||||
이 값 사용 불가.
|
||||
|
||||
'
|
||||
proxy_detection:
|
||||
proxy_flag_field: t20_is_proxy
|
||||
proxy_value: t5_operational_proxy
|
||||
source_field: outcome_quality_score_v1.json.metrics.t20_source
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
formula_id: CANONICAL_METRICS_REGISTRY_V1
|
||||
has_code_implementation: true
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
metrics:
|
||||
cash_min_required_krw:
|
||||
canonical_source: cash_recovery_display_json.min_required_krw
|
||||
consumers:
|
||||
- exec_safety_declaration
|
||||
- cash_recovery_plan_crdl
|
||||
- single_conclusion
|
||||
- QEH_AUDIT_BLOCK
|
||||
description: 현금 최소 필요액(원) — cash_floor 확보를 위한 최소 매도 필요 금액
|
||||
fallback_sources:
|
||||
- cash_shortfall_min_krw
|
||||
- trim_plan_to_min_cash_json.cash_shortfall_min_krw
|
||||
notes: 'cash_shortfall_json 객체가 None이므로 cash_shortfall_json.cash_shortfall_min_krw
|
||||
읽기 불가. harness_context 최상위 cash_shortfall_min_krw=39797073이 대안이나, canonical
|
||||
= cash_recovery_display_json.min_required_krw(39797073).
|
||||
|
||||
'
|
||||
tolerance_abs: 0
|
||||
unit: krw
|
||||
cash_reference_total_krw:
|
||||
canonical_source: trim_plan_to_min_cash_json.total_plan_krw
|
||||
consumers:
|
||||
- cash_recovery_plan_crdl
|
||||
description: 현금확보 전체 후보 누적 금액(원) — 주문 아님, 참고용
|
||||
fallback_sources:
|
||||
- cash_recovery_display_json.reference_total_krw
|
||||
notes: 'cash_recovery_display_json.reference_total_krw=0(미산출). 올바른 원천 = trim_plan_to_min_cash_json.total_plan_krw(227,868,540).
|
||||
|
||||
'
|
||||
tolerance_abs: 0
|
||||
unit: krw
|
||||
cluster_pct:
|
||||
canonical_source: semiconductor_cluster_json.combined_pct
|
||||
consumers:
|
||||
- cluster_sync_audit
|
||||
- portfolio_structure_risks
|
||||
- mandatory_reduction_plan
|
||||
description: 반도체 클러스터(삼성전자+SK하이닉스+KODEX반도체) 합산 비중(%)
|
||||
fallback_sources:
|
||||
- mandatory_reduction_json.cluster_pct
|
||||
- cluster_sync_result_json.cluster_pct
|
||||
notes: 'cluster_sync_result_json.cluster_pct=0 버그가 있음. mandatory_reduction_json.cluster_pct=62.79는
|
||||
소수점 반올림 차이이므로 tolerance 허용. canonical = semiconductor_cluster_json.combined_pct(62.93).
|
||||
|
||||
'
|
||||
tolerance_abs: 0.05
|
||||
unit: percent
|
||||
per_ticker_metrics:
|
||||
scrs_immediate_qty:
|
||||
alias_in_data: immediate_qty
|
||||
canonical_source: scrs_v2_json.selected_combo[ticker].immediate_qty
|
||||
consumers:
|
||||
- scrs_v2_sell_table
|
||||
description: SCRS-V2 즉시 매도 수량(주)
|
||||
notes: '렌더러가 immediate_sell_qty를 찾지만 데이터에는 immediate_qty가 있음. AGENTS.md 5b: "immediate_sell_qty는
|
||||
''-'' 출력 금지 (키 불일치)" 명시 위반.
|
||||
|
||||
'
|
||||
wrong_alias_in_renderer: immediate_sell_qty
|
||||
scrs_rebound_qty:
|
||||
alias_in_data: rebound_wait_qty
|
||||
canonical_source: scrs_v2_json.selected_combo[ticker].rebound_wait_qty
|
||||
consumers:
|
||||
- scrs_v2_sell_table
|
||||
description: SCRS-V2 반등 대기 수량(주)
|
||||
ticker_base_qty:
|
||||
canonical_source: sell_quantities_json[ticker].sell_qty
|
||||
consumers:
|
||||
- shadow_ledger_table
|
||||
description: 종목별 기준 매도 수량(주)
|
||||
fallback_sources:
|
||||
- comprehensive_proposal_json[ticker].quantity
|
||||
notes: 'shadow_ledger_json의 base_qty_calc=None. sell_quantities_json[].sell_qty
|
||||
또는 comprehensive_proposal_json[].quantity 사용.
|
||||
|
||||
'
|
||||
ticker_limit_price:
|
||||
canonical_source: proposal_reference_json[ticker].proposed_limit_price_krw
|
||||
consumers:
|
||||
- shadow_ledger_table
|
||||
description: 종목별 산출 지정가(원) — 차단 종목 포함 전체 표시(H10)
|
||||
fallback_sources:
|
||||
- prices_json[ticker].stop_price
|
||||
notes: 'AGENTS.md H10: 차단 종목도 산출 지표 은폐 금지. proposal_reference_json에 proposed_limit_price_krw가
|
||||
있으면 사용, 없으면 prices_json.stop_price를 참고방어가로 표시.
|
||||
|
||||
'
|
||||
ticker_profit_pct:
|
||||
alias_in_renderer_correct: profit_pct
|
||||
alias_in_renderer_wrong: unrealized_pnl_pct
|
||||
canonical_source: prices_json[ticker].profit_pct
|
||||
consumers:
|
||||
- profit_preservation_table
|
||||
description: 종목별 미실현 손익률(%)
|
||||
notes: 'profit_preservation_json[].unrealized_pnl_pct=None. 올바른 원천 = prices_json[].profit_pct.
|
||||
|
||||
'
|
||||
ticker_stop_price:
|
||||
canonical_source: prices_json[ticker].stop_price
|
||||
consumers:
|
||||
- shadow_ledger_table
|
||||
- profit_preservation_table
|
||||
description: 종목별 손절가(원)
|
||||
notes: shadow_ledger_json의 stop_loss_calc=None이므로 prices_json 직접 사용.
|
||||
ticker_tp1_price:
|
||||
canonical_source: prices_json[ticker].tp1_price
|
||||
consumers:
|
||||
- shadow_ledger_table
|
||||
description: 종목별 1차 익절가(원)
|
||||
v11_contradiction_metrics:
|
||||
cash_immediately_raisable_krw:
|
||||
canonical_source: cash_recovery_optimizer_v4.json.cash_shortfall_min_krw
|
||||
contradiction_sites:
|
||||
- section: cash_recovery_plan_crdl
|
||||
value: 57841575
|
||||
- section: engine_audit_sell_classification
|
||||
value: 59399085
|
||||
description: 즉시 조달 가능 현금(원)
|
||||
fallback_sources:
|
||||
- smart_cash_recovery_v8.json.cash_recovered_krw
|
||||
tolerance_abs: 0
|
||||
unit: krw
|
||||
cash_shortfall_target_krw:
|
||||
canonical_source: cash_recovery_optimizer_v4.json.cash_shortfall_min_krw
|
||||
contradiction_sites:
|
||||
- section: executive_brief
|
||||
value: 38671178
|
||||
- section: single_conclusion
|
||||
value: 47769737
|
||||
description: 현금 목표 부족액(원)
|
||||
fallback_sources:
|
||||
- operational_truth_score_v1.json.cash_shortfall_min_krw
|
||||
tolerance_abs: 0
|
||||
unit: krw
|
||||
confidence_cap:
|
||||
canonical_source: imputed_data_exposure_gate_v2.json.effective_confidence_honest
|
||||
contradiction_sites:
|
||||
- note: schema_presence 기반 — 거짓
|
||||
section: investment_quality_headline
|
||||
value: 93.0
|
||||
- note: honest 기반 — canonical
|
||||
section: engine_audit_imputed_exposure_honest
|
||||
value: 88.4
|
||||
description: 신뢰도 캡(0~100) — honest 기준
|
||||
notes: 88.4가 canonical. 93.0은 schema_presence 기반 거짓 캡이므로 폐기.
|
||||
tolerance_abs: 0.1
|
||||
unit: score
|
||||
final_score:
|
||||
canonical_source: scores_harness_v1.json.final_score.value
|
||||
contradiction_sites:
|
||||
- section: engine_audit_scores
|
||||
value: 40.5
|
||||
- note: 재계산값 — canonical 40.5 사용
|
||||
section: performance_monitoring_dashboard
|
||||
value: 45.3
|
||||
description: 종합 전략 점수(0~100)
|
||||
tolerance_abs: 0.5
|
||||
unit: score
|
||||
horizon_cap_mid_pct:
|
||||
canonical_source: horizon_allocation_guard_v2.json.mid_cap
|
||||
contradiction_sites:
|
||||
- section: horizon_allocation_lock_v1
|
||||
value: 45
|
||||
- section: engine_audit_routing
|
||||
value: 50
|
||||
description: 중기 호라이즌 비중 상한(%)
|
||||
tolerance_abs: 1.0
|
||||
unit: percent
|
||||
horizon_cap_short_pct:
|
||||
canonical_source: horizon_allocation_guard_v2.json.short_cap
|
||||
description: 단기 호라이즌 비중 상한(%)
|
||||
fallback_sources:
|
||||
- spec/strategy/horizon_allocation_v1.yaml.rules.HA002.condition
|
||||
notes: 엔진 감사 short_cap=40%, horizon_routing_lock short_threshold=40%
|
||||
tolerance_abs: 1.0
|
||||
unit: percent
|
||||
mid_horizon_pct:
|
||||
canonical_source: horizon_classification_v1.json.allocation_pct.MID
|
||||
description: 중기 호라이즌 비중(%)
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
operational_truth_score:
|
||||
canonical_source: operational_truth_score_v1.json.score_0_100
|
||||
contradiction_sites:
|
||||
- section: operational_truth_score_section
|
||||
value: 80.86
|
||||
- note: 재계산값 — canonical 80.86 사용
|
||||
section: performance_monitoring_dashboard
|
||||
value: 89.12
|
||||
description: 운영 진실 점수(0~100)
|
||||
tolerance_abs: 0.1
|
||||
unit: score
|
||||
performance_readiness_score:
|
||||
canonical_source: operational_truth_score_v1.json.performance_readiness_score
|
||||
contradiction_sites:
|
||||
- section: operational_truth_score_section
|
||||
value: 37.2
|
||||
- note: 50은 비활성 기본값 — canonical 37.2 사용
|
||||
section: performance_monitoring_dashboard
|
||||
value: 50.0
|
||||
description: 성과 준비도 점수(0~100)
|
||||
tolerance_abs: 0.1
|
||||
unit: score
|
||||
position_weight_pct:
|
||||
canonical_source: portfolio_exposure_v1.json[ticker].weight_pct
|
||||
contradiction_sites:
|
||||
- samsung: 44.5
|
||||
section: portfolio_risk_panel
|
||||
- samsung: 44.35
|
||||
section: ejce
|
||||
- samsung: 45.5
|
||||
section: executive
|
||||
description: 종목별 포트폴리오 비중(%)
|
||||
fallback_sources:
|
||||
- prices_json[ticker].position_weight_pct
|
||||
per_ticker: true
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
short_horizon_pct:
|
||||
canonical_source: horizon_classification_v1.json.allocation_pct.SHORT
|
||||
contradiction_sites:
|
||||
- section: horizon_allocation_lock_v1
|
||||
value: 14.3
|
||||
- note: 보유종목 SHORT비중과 전략노출 혼동
|
||||
section: performance_monitoring_dashboard
|
||||
value: 71.4
|
||||
description: 단기 호라이즌 비중(%)
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
t5_match_rate_pct:
|
||||
canonical_source: prediction_accuracy_harness_v5.json.prediction_match_rate_pct
|
||||
contradiction_sites:
|
||||
- note: 전체 이력 기준
|
||||
section: outcome_eval_window_monitor
|
||||
value: 35.69
|
||||
- note: decisive 케이스만 — 혼용 금지
|
||||
section: performance_monitoring_dashboard
|
||||
value: 73.24
|
||||
description: T+5 예측 방향 일치율(%)
|
||||
fallback_sources:
|
||||
- outcome_quality_score_v1.json.metrics.t5_operational_pass_rate
|
||||
notes: canonical = prediction_accuracy_harness_v5.prediction_match_rate_pct(47.28).
|
||||
표본 정의 혼용 금지.
|
||||
tolerance_abs: 0.5
|
||||
unit: percent
|
||||
unrealized_return_pct:
|
||||
canonical_source: prices_json[ticker].profit_pct
|
||||
contradiction_sites:
|
||||
- samsung: 98.0
|
||||
section: position_dashboard
|
||||
- samsung: 96.44
|
||||
section: profit_preservation_table
|
||||
- samsung: 96.4
|
||||
section: decision_trace
|
||||
description: 종목별 미실현 수익률(%)
|
||||
per_ticker: true
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
value_damage_pct:
|
||||
canonical_source: smart_cash_recovery_v8.json.raw_value_damage_pct_avg
|
||||
contradiction_sites:
|
||||
- correct_value: 15.7
|
||||
section: final_execution_decision
|
||||
wrong_value: 0.0
|
||||
- correct_value: 15.7
|
||||
section: cash_recovery_plan_crdl
|
||||
wrong_value: 0.0
|
||||
description: 현금확보 매도의 가치훼손율(%) — raw 기준
|
||||
fallback_sources:
|
||||
- smart_cash_recovery_v7.json.raw_value_damage_pct_avg
|
||||
- smart_cash_recovery_v9.json.raw_value_damage_pct_avg
|
||||
notes: raw=15.7%가 canonical. adjusted=0.0 단독 표기는 RAW_VS_ADJUSTED_DISCLOSURE_V1
|
||||
위반.
|
||||
tolerance_abs: 0.1
|
||||
unit: percent
|
||||
version: '2026-05-29'
|
||||
|
||||
@@ -1,408 +1,365 @@
|
||||
behavioral_coverage_contract:
|
||||
behavioral_coverage_definition:
|
||||
denominator: 숫자·enum 출력을 가진 decision-critical 공식 수
|
||||
formula: behavioral_coverage_pct = (numerator / denominator) * 100
|
||||
numerator: ≥1개 golden case가 PASS인 decision-critical 공식 수
|
||||
pass_threshold: 100.0
|
||||
code_path: tools/validate_behavioral_coverage_v1.py
|
||||
completion_gate:
|
||||
behavioral_coverage_pct_min: 100.0
|
||||
golden_case_min_per_formula: 1
|
||||
implementation_divergence_count_max: 0
|
||||
provenance_allowed:
|
||||
- HAND_COMPUTED
|
||||
- SPEC_DERIVED
|
||||
decision_critical_formulas:
|
||||
- category: price
|
||||
gas_file: gas_lib.gs
|
||||
gas_function: tickNormalize_
|
||||
id: TICK_NORMALIZER_V1
|
||||
known_divergence: GAS=Math.floor, Python=round → 비정확 배수에서 결과 상이
|
||||
milestone: 1
|
||||
python_mirror: compute_formula_outputs.normalize_tick
|
||||
spec_intent: KRX HTS 입력용 floor-to-tick (GAS 동작이 spec 의도에 부합)
|
||||
- category: price
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcSellPriceSanityV2_
|
||||
id: SELL_PRICE_SANITY_V1
|
||||
milestone: 1
|
||||
note: GAS V2 함수명 상이 — 로직 일치 여부 검증 필요
|
||||
python_mirror: compute_formula_outputs.check_sell_price_sanity
|
||||
- category: price
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: null
|
||||
id: PULLBACK_ENTRY_TRIGGER_V1
|
||||
milestone: 1
|
||||
note: GAS에서 calcPullbackTrigger_ 독립 함수 미확인 — calcAntiLateEntryGateV2Impl_ 내부 로직으로
|
||||
통합
|
||||
python_mirror: compute_formula_outputs.compute_pullback_trigger
|
||||
- category: price
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: null
|
||||
id: PROFIT_RATCHET_TIERED_V2
|
||||
milestone: 1
|
||||
note: GAS calcPrices_ 내부에 인라인 — 독립 함수 미확인
|
||||
python_mirror: compute_formula_outputs.compute_trailing_stop_v2
|
||||
- category: price
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: null
|
||||
id: PROFIT_LOCK_STAGE_V1
|
||||
known_divergence: 'Python: APEX_SUPER(>=60),APEX_TRAILING(>=40),PROFIT_LOCK_30,PROFIT_LOCK_20,PROFIT_LOCK_10,BREAKEVEN_RATCHET,NORMAL
|
||||
|
||||
GAS calcPrices_: PROFIT_LOCK_STAGE_50(>=50),PROFIT_LOCK_STAGE_30,PROFIT_LOCK_STAGE_20,PROFIT_LOCK_STAGE_10,NORMAL
|
||||
|
||||
stage 명칭·임계값 모두 불일치 — B06 정정 필수
|
||||
|
||||
'
|
||||
milestone: 1
|
||||
python_mirror: compute_formula_outputs.classify_profit_lock_stage
|
||||
- category: price
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcStopAdequacyRows_
|
||||
id: STOP_PRICE_ADEQUACY_V1
|
||||
milestone: 1
|
||||
note: Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가 필요
|
||||
python_mirror: null
|
||||
- category: sizing
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcRegimeSizeScale_
|
||||
id: POSITION_SIZE_REGIME_SCALE_V1
|
||||
milestone: 1
|
||||
note: Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가
|
||||
python_mirror: null
|
||||
- category: sizing
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcDrawdownGuard_
|
||||
id: DRAWDOWN_GUARD_V1
|
||||
milestone: 1
|
||||
note: Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가
|
||||
python_mirror: null
|
||||
- category: sizing
|
||||
gas_file: null
|
||||
gas_function: null
|
||||
id: CASH_RECOVERY_OPTIMIZER_V1
|
||||
milestone: 1
|
||||
note: Python-only formula. GAS 미러 없음(Python tool 전용).
|
||||
python_mirror: compute_formula_outputs.compute_cash_recovery_optimizer
|
||||
- category: sizing
|
||||
gas_function: null
|
||||
id: VALUE_PRESERVATION_SCORER_V1
|
||||
milestone: 1
|
||||
note: tools/build_value_preservation_scorer_v1.py 전용 — Python 미러 추출 필요
|
||||
python_mirror: null
|
||||
- category: sizing
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcTpQuantityLadder_
|
||||
id: TP_QUANTITY_LADDER_V1
|
||||
milestone: 2
|
||||
- category: entry_gate
|
||||
gas_function: inline_calcAntiLateEntryGateV2Impl_
|
||||
id: VELOCITY_V1
|
||||
milestone: 1
|
||||
note: velocity_1d = (close-prevClose)/prevClose*100 — 양측 인라인 계산
|
||||
python_mirror: inline
|
||||
- category: entry_gate
|
||||
gas_file: gas_apex_alpha_watch.gs
|
||||
gas_function: calcAntiLateEntryGateV2Impl_
|
||||
id: ANTI_LATE_ENTRY_GATE_V2
|
||||
milestone: 1
|
||||
note: Python에서 gate1만 compute_anti_chasing으로 분리됨 — 전체 3-gate 검증은 GAS 위주
|
||||
python_mirror: null
|
||||
- category: entry_gate
|
||||
gas_function: null
|
||||
id: ANTI_CHASING_VELOCITY_V1
|
||||
milestone: 1
|
||||
note: ANTI_LATE_ENTRY_GATE_V2의 gate1 서브셋 — Python 독립 구현
|
||||
python_mirror: compute_formula_outputs.compute_anti_chasing
|
||||
- category: entry_gate
|
||||
gas_function: null
|
||||
id: FLOW_CREDIT_V1
|
||||
milestone: 2
|
||||
note: GAS 내부 인라인 — spec/13_formula_registry.yaml expression 존재
|
||||
- category: entry_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcBreakoutQualityGate_
|
||||
id: BREAKOUT_QUALITY_GATE_V2
|
||||
milestone: 2
|
||||
- category: entry_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcAntiWhipsawGate_
|
||||
id: ANTI_WHIPSAW_GATE_V1
|
||||
milestone: 2
|
||||
- category: entry_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcPositionCountLimit_
|
||||
id: POSITION_COUNT_LIMIT_V1
|
||||
milestone: 1
|
||||
note: Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가
|
||||
python_mirror: null
|
||||
- category: entry_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcWinLossStreakGuard_
|
||||
id: WIN_LOSS_STREAK_GUARD_V1
|
||||
milestone: 2
|
||||
- category: distribution
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcDistributionRiskRow_
|
||||
id: DISTRIBUTION_SELL_DETECTOR_V1
|
||||
milestone: 2
|
||||
note: 6+2 신호 가중합산. SIG_5(OBV기울기) GAS 구현 확인 필요
|
||||
- category: distribution
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcDistributionRiskRow_
|
||||
id: PRE_DISTRIBUTION_EARLY_WARNING_V1
|
||||
milestone: 2
|
||||
note: calcDistributionRiskRow_ 내 pre_distribution_warning 필드로 출력
|
||||
- category: distribution
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcSectorRotationMomentum_
|
||||
id: SECTOR_ROTATION_MOMENTUM_V1
|
||||
milestone: 2
|
||||
- category: cash_sell
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcDynamicHeatThresholds_
|
||||
id: DYNAMIC_HEAT_GATE_V1
|
||||
milestone: 1
|
||||
note: Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가
|
||||
python_mirror: null
|
||||
- category: cash_sell
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcCashFloor_
|
||||
id: CASH_FLOOR_V1
|
||||
milestone: 1
|
||||
note: Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가
|
||||
python_mirror: null
|
||||
- category: cash_sell
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcCashShortfallHarness_
|
||||
id: CASH_SHORTFALL_V1
|
||||
milestone: 2
|
||||
- category: cash_sell
|
||||
gas_function: null
|
||||
id: K2_STAGED_REBOUND_SELL_V1
|
||||
milestone: 2
|
||||
note: spec/13b_harness_formulas.yaml에 정의. GAS calcApexTradePlan_ 내부
|
||||
- category: cash_sell
|
||||
id: SELL_WATERFALL_ENGINE_V2
|
||||
milestone: 2
|
||||
note: tools/build_sell_waterfall_engine_v2.py 전용
|
||||
python_mirror: null
|
||||
- category: cash_sell
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcRegimeTrimGuidance_
|
||||
id: REGIME_TRIM_GUIDANCE_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcRegimeCashUplift_
|
||||
id: REGIME_CASH_UPLIFT_V1
|
||||
milestone: 1
|
||||
note: Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가
|
||||
python_mirror: null
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcSemiconductorClusterGate_
|
||||
id: SEMICONDUCTOR_CLUSTER_GATE_V1
|
||||
milestone: 1
|
||||
note: Python 미러 미구현
|
||||
python_mirror: null
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcSinglePositionWeightCap_
|
||||
id: SINGLE_POSITION_WEIGHT_CAP_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcPortfolioBetaGate_
|
||||
id: PORTFOLIO_BETA_GATE_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcSectorConcentrationGate_
|
||||
id: SECTOR_CONCENTRATION_LIMIT_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcPortfolioDrawdownGate_
|
||||
id: PORTFOLIO_DRAWDOWN_GATE_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
id: FINAL_JUDGMENT_GATE_V1
|
||||
milestone: 2
|
||||
note: tools/build_final_judgment_gate_v1.py 전용 — AND-11 복합 게이트
|
||||
python_mirror: null
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcStopBreachAlert_
|
||||
id: STOP_BREACH_ALERT_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcTpTriggerAlert_
|
||||
id: TP_TRIGGER_ALERT_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcHeatConcentrationAlert_
|
||||
id: HEAT_CONCENTRATION_ALERT_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcPortfolioHealthScore_
|
||||
id: PORTFOLIO_HEALTH_SCORE_V1
|
||||
milestone: 2
|
||||
- category: portfolio_gate
|
||||
gas_file: gas_data_feed.gs
|
||||
gas_function: calcProfitPreservationRow_
|
||||
id: BREAKEVEN_RATCHET_V1
|
||||
milestone: 2
|
||||
evidence_artifacts:
|
||||
- Temp/formula_behavioral_coverage_v1.json
|
||||
- Temp/formula_gas_parity_v1.json
|
||||
formula_id: BEHAVIORAL_COVERAGE_CONTRACT_V1
|
||||
has_code_implementation: true
|
||||
code_path: "tools/validate_behavioral_coverage_v1.py"
|
||||
version: "2026-05-30"
|
||||
objective: |
|
||||
"formula_id 문자열이 .gs 텍스트에 등장한다" 는 문자열 커버리지(presence-based)를 폐기하고
|
||||
"주어진 입력에 대해 golden(손계산 정답) == Python미러 == GAS미러 가 허용오차 내 일치한다"
|
||||
는 행위기반 커버리지(behavioral coverage)로 전환한다.
|
||||
구조적 거짓(결함 1)을 제거하기 위한 근본 측정 기반.
|
||||
|
||||
# 수치로 정의된 완료점 (completion gate)
|
||||
completion_gate:
|
||||
behavioral_coverage_pct_min: 100.0 # decision-critical 공식 전부 1개 이상 통과 케이스
|
||||
implementation_divergence_count_max: 0 # Python 미러 ≠ GAS 미러 건수 반드시 0
|
||||
golden_case_min_per_formula: 1 # 공식당 최소 1개 golden case 필수
|
||||
provenance_allowed: # expected 값의 허용 출처 — 구현 역복사 금지
|
||||
- HAND_COMPUTED # 공식 정의(spec/13)에서 손으로 1회 계산
|
||||
- SPEC_DERIVED # spec/13 expression을 기계적 치환한 결과
|
||||
|
||||
# 행위기반 커버리지 정의
|
||||
behavioral_coverage_definition:
|
||||
numerator: "≥1개 golden case가 PASS인 decision-critical 공식 수"
|
||||
denominator: "숫자·enum 출력을 가진 decision-critical 공식 수"
|
||||
formula: "behavioral_coverage_pct = (numerator / denominator) * 100"
|
||||
pass_threshold: 100.0
|
||||
|
||||
# 3-way 동등성 게이트
|
||||
three_way_gate:
|
||||
python_vs_golden_tolerance: "각 공식 케이스 yaml의 tolerance 필드 기준"
|
||||
gas_vs_golden_tolerance: "동일"
|
||||
divergence_definition: |
|
||||
python_output ≠ gas_output (허용오차 초과) 이면 IMPLEMENTATION_DIVERGENCE.
|
||||
이는 "yaml 지침과 구현이 다른 숫자를 낸다"는 직접 증거이며 B06에서 근본 정정 필요.
|
||||
divergence_resolution: |
|
||||
spec/13_formula_registry.yaml 의 expression이 기준.
|
||||
GAS 또는 Python 중 spec에서 벗어난 쪽을 수정한다.
|
||||
LLM 추정으로 수정 금지. spec expression 기계적 적용.
|
||||
|
||||
# decision-critical 40개 공식 명단
|
||||
# milestone_1 = 이번 작업(golden case 작성 + 3-way 검증 대상)
|
||||
# milestone_2 = 후속 단계
|
||||
decision_critical_formulas:
|
||||
|
||||
# ── 가격 산출 공식 (6) ──────────────────────────────────────────────
|
||||
- id: TICK_NORMALIZER_V1
|
||||
milestone: 1
|
||||
category: price
|
||||
python_mirror: compute_formula_outputs.normalize_tick
|
||||
gas_function: tickNormalize_
|
||||
gas_file: gas_lib.gs
|
||||
known_divergence: "GAS=Math.floor, Python=round → 비정확 배수에서 결과 상이"
|
||||
spec_intent: "KRX HTS 입력용 floor-to-tick (GAS 동작이 spec 의도에 부합)"
|
||||
|
||||
- id: SELL_PRICE_SANITY_V1
|
||||
milestone: 1
|
||||
category: price
|
||||
python_mirror: compute_formula_outputs.check_sell_price_sanity
|
||||
gas_function: calcSellPriceSanityV2_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "GAS V2 함수명 상이 — 로직 일치 여부 검증 필요"
|
||||
|
||||
- id: PULLBACK_ENTRY_TRIGGER_V1
|
||||
milestone: 1
|
||||
category: price
|
||||
python_mirror: compute_formula_outputs.compute_pullback_trigger
|
||||
gas_function: null
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "GAS에서 calcPullbackTrigger_ 독립 함수 미확인 — calcAntiLateEntryGateV2Impl_ 내부 로직으로 통합"
|
||||
|
||||
- id: PROFIT_RATCHET_TIERED_V2
|
||||
milestone: 1
|
||||
category: price
|
||||
python_mirror: compute_formula_outputs.compute_trailing_stop_v2
|
||||
gas_function: null
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "GAS calcPrices_ 내부에 인라인 — 독립 함수 미확인"
|
||||
|
||||
- id: PROFIT_LOCK_STAGE_V1
|
||||
milestone: 1
|
||||
category: price
|
||||
python_mirror: compute_formula_outputs.classify_profit_lock_stage
|
||||
gas_function: null
|
||||
gas_file: gas_data_feed.gs
|
||||
known_divergence: |
|
||||
Python: APEX_SUPER(>=60),APEX_TRAILING(>=40),PROFIT_LOCK_30,PROFIT_LOCK_20,PROFIT_LOCK_10,BREAKEVEN_RATCHET,NORMAL
|
||||
GAS calcPrices_: PROFIT_LOCK_STAGE_50(>=50),PROFIT_LOCK_STAGE_30,PROFIT_LOCK_STAGE_20,PROFIT_LOCK_STAGE_10,NORMAL
|
||||
stage 명칭·임계값 모두 불일치 — B06 정정 필수
|
||||
|
||||
- id: STOP_PRICE_ADEQUACY_V1
|
||||
milestone: 1
|
||||
category: price
|
||||
python_mirror: null
|
||||
gas_function: calcStopAdequacyRows_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가 필요"
|
||||
|
||||
# ── 수량·사이징 공식 (5) ────────────────────────────────────────────
|
||||
- id: POSITION_SIZE_REGIME_SCALE_V1
|
||||
milestone: 1
|
||||
category: sizing
|
||||
python_mirror: null
|
||||
gas_function: calcRegimeSizeScale_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가"
|
||||
|
||||
- id: DRAWDOWN_GUARD_V1
|
||||
milestone: 1
|
||||
category: sizing
|
||||
python_mirror: null
|
||||
gas_function: calcDrawdownGuard_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가"
|
||||
|
||||
- id: CASH_RECOVERY_OPTIMIZER_V1
|
||||
milestone: 1
|
||||
category: sizing
|
||||
python_mirror: compute_formula_outputs.compute_cash_recovery_optimizer
|
||||
gas_function: null
|
||||
gas_file: null
|
||||
note: "Python-only formula. GAS 미러 없음(Python tool 전용)."
|
||||
|
||||
- id: VALUE_PRESERVATION_SCORER_V1
|
||||
milestone: 1
|
||||
category: sizing
|
||||
python_mirror: null
|
||||
gas_function: null
|
||||
note: "tools/build_value_preservation_scorer_v1.py 전용 — Python 미러 추출 필요"
|
||||
|
||||
- id: TP_QUANTITY_LADDER_V1
|
||||
milestone: 2
|
||||
category: sizing
|
||||
gas_function: calcTpQuantityLadder_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
# ── 진입 게이트 공식 (8) ────────────────────────────────────────────
|
||||
- id: VELOCITY_V1
|
||||
milestone: 1
|
||||
category: entry_gate
|
||||
python_mirror: inline
|
||||
gas_function: inline_calcAntiLateEntryGateV2Impl_
|
||||
note: "velocity_1d = (close-prevClose)/prevClose*100 — 양측 인라인 계산"
|
||||
|
||||
- id: ANTI_LATE_ENTRY_GATE_V2
|
||||
milestone: 1
|
||||
category: entry_gate
|
||||
python_mirror: null
|
||||
gas_function: calcAntiLateEntryGateV2Impl_
|
||||
gas_file: gas_apex_alpha_watch.gs
|
||||
note: "Python에서 gate1만 compute_anti_chasing으로 분리됨 — 전체 3-gate 검증은 GAS 위주"
|
||||
|
||||
- id: ANTI_CHASING_VELOCITY_V1
|
||||
milestone: 1
|
||||
category: entry_gate
|
||||
python_mirror: compute_formula_outputs.compute_anti_chasing
|
||||
gas_function: null
|
||||
note: "ANTI_LATE_ENTRY_GATE_V2의 gate1 서브셋 — Python 독립 구현"
|
||||
|
||||
- id: FLOW_CREDIT_V1
|
||||
milestone: 2
|
||||
category: entry_gate
|
||||
gas_function: null
|
||||
note: "GAS 내부 인라인 — spec/13_formula_registry.yaml expression 존재"
|
||||
|
||||
- id: BREAKOUT_QUALITY_GATE_V2
|
||||
milestone: 2
|
||||
category: entry_gate
|
||||
gas_function: calcBreakoutQualityGate_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: ANTI_WHIPSAW_GATE_V1
|
||||
milestone: 2
|
||||
category: entry_gate
|
||||
gas_function: calcAntiWhipsawGate_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: POSITION_COUNT_LIMIT_V1
|
||||
milestone: 1
|
||||
category: entry_gate
|
||||
python_mirror: null
|
||||
gas_function: calcPositionCountLimit_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가"
|
||||
|
||||
- id: WIN_LOSS_STREAK_GUARD_V1
|
||||
milestone: 2
|
||||
category: entry_gate
|
||||
gas_function: calcWinLossStreakGuard_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
# ── 분배·설거지 탐지 공식 (3) ──────────────────────────────────────
|
||||
- id: DISTRIBUTION_SELL_DETECTOR_V1
|
||||
milestone: 2
|
||||
category: distribution
|
||||
gas_function: calcDistributionRiskRow_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "6+2 신호 가중합산. SIG_5(OBV기울기) GAS 구현 확인 필요"
|
||||
|
||||
- id: PRE_DISTRIBUTION_EARLY_WARNING_V1
|
||||
milestone: 2
|
||||
category: distribution
|
||||
gas_function: calcDistributionRiskRow_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "calcDistributionRiskRow_ 내 pre_distribution_warning 필드로 출력"
|
||||
|
||||
- id: SECTOR_ROTATION_MOMENTUM_V1
|
||||
milestone: 2
|
||||
category: distribution
|
||||
gas_function: calcSectorRotationMomentum_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
# ── 현금·매도 엔진 공식 (6) ────────────────────────────────────────
|
||||
- id: DYNAMIC_HEAT_GATE_V1
|
||||
milestone: 1
|
||||
category: cash_sell
|
||||
python_mirror: null
|
||||
gas_function: calcDynamicHeatThresholds_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가"
|
||||
|
||||
- id: CASH_FLOOR_V1
|
||||
milestone: 1
|
||||
category: cash_sell
|
||||
python_mirror: null
|
||||
gas_function: calcCashFloor_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가"
|
||||
|
||||
- id: CASH_SHORTFALL_V1
|
||||
milestone: 2
|
||||
category: cash_sell
|
||||
gas_function: calcCashShortfallHarness_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: K2_STAGED_REBOUND_SELL_V1
|
||||
milestone: 2
|
||||
category: cash_sell
|
||||
gas_function: null
|
||||
note: "spec/13b_harness_formulas.yaml에 정의. GAS calcApexTradePlan_ 내부"
|
||||
|
||||
- id: SELL_WATERFALL_ENGINE_V2
|
||||
milestone: 2
|
||||
category: cash_sell
|
||||
python_mirror: null
|
||||
note: "tools/build_sell_waterfall_engine_v2.py 전용"
|
||||
|
||||
- id: REGIME_TRIM_GUIDANCE_V1
|
||||
milestone: 2
|
||||
category: cash_sell
|
||||
gas_function: calcRegimeTrimGuidance_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
# ── 포트폴리오 게이트 공식 (12) ────────────────────────────────────
|
||||
- id: REGIME_CASH_UPLIFT_V1
|
||||
milestone: 1
|
||||
category: portfolio_gate
|
||||
python_mirror: null
|
||||
gas_function: calcRegimeCashUplift_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "Python 미러 미구현 — run_formula_golden_cases_v2.py에 추가"
|
||||
|
||||
- id: SEMICONDUCTOR_CLUSTER_GATE_V1
|
||||
milestone: 1
|
||||
category: portfolio_gate
|
||||
python_mirror: null
|
||||
gas_function: calcSemiconductorClusterGate_
|
||||
gas_file: gas_data_feed.gs
|
||||
note: "Python 미러 미구현"
|
||||
|
||||
- id: SINGLE_POSITION_WEIGHT_CAP_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcSinglePositionWeightCap_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: PORTFOLIO_BETA_GATE_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcPortfolioBetaGate_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: SECTOR_CONCENTRATION_LIMIT_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcSectorConcentrationGate_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: PORTFOLIO_DRAWDOWN_GATE_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcPortfolioDrawdownGate_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: FINAL_JUDGMENT_GATE_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
python_mirror: null
|
||||
note: "tools/build_final_judgment_gate_v1.py 전용 — AND-11 복합 게이트"
|
||||
|
||||
- id: STOP_BREACH_ALERT_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcStopBreachAlert_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: TP_TRIGGER_ALERT_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcTpTriggerAlert_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: HEAT_CONCENTRATION_ALERT_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcHeatConcentrationAlert_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: PORTFOLIO_HEALTH_SCORE_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcPortfolioHealthScore_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
- id: BREAKEVEN_RATCHET_V1
|
||||
milestone: 2
|
||||
category: portfolio_gate
|
||||
gas_function: calcProfitPreservationRow_
|
||||
gas_file: gas_data_feed.gs
|
||||
|
||||
# milestone_1+2 달성 현황 (2026-05-30 기준) — 실제 골든케이스 보유 공식
|
||||
milestone_1_count: 37
|
||||
milestone_1_target_formulas:
|
||||
# 원래 milestone_1 (18개)
|
||||
- TICK_NORMALIZER_V1
|
||||
- SELL_PRICE_SANITY_V1
|
||||
- PULLBACK_ENTRY_TRIGGER_V1
|
||||
- PROFIT_RATCHET_TIERED_V2
|
||||
- PROFIT_LOCK_STAGE_V1
|
||||
- STOP_PRICE_ADEQUACY_V1
|
||||
- POSITION_SIZE_REGIME_SCALE_V1
|
||||
- DRAWDOWN_GUARD_V1
|
||||
- CASH_RECOVERY_OPTIMIZER_V1
|
||||
- VALUE_PRESERVATION_SCORER_V1
|
||||
- VELOCITY_V1
|
||||
- ANTI_LATE_ENTRY_GATE_V2
|
||||
- ANTI_CHASING_VELOCITY_V1
|
||||
- POSITION_COUNT_LIMIT_V1
|
||||
- DYNAMIC_HEAT_GATE_V1
|
||||
- CASH_FLOOR_V1
|
||||
- REGIME_CASH_UPLIFT_V1
|
||||
- SEMICONDUCTOR_CLUSTER_GATE_V1
|
||||
# milestone_2 달성 (추가 19개)
|
||||
- WIN_LOSS_STREAK_GUARD_V1
|
||||
- SINGLE_POSITION_WEIGHT_CAP_V1 # LEADER_POSITION_WEIGHT_CAP_V1로 강화
|
||||
- REGIME_TRIM_GUIDANCE_V1
|
||||
- HEAT_CONCENTRATION_ALERT_V1
|
||||
- SECTOR_CONCENTRATION_LIMIT_V1
|
||||
- CASH_SHORTFALL_V1
|
||||
- K2_STAGED_REBOUND_SELL_V1
|
||||
- PORTFOLIO_DRAWDOWN_GATE_V1
|
||||
- PROFIT_LOCK_STAGE_V1 # GAS 단계명 정정 포함 (B06)
|
||||
# 반도체 집중 허용 하네스 (신규)
|
||||
- MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1
|
||||
- LEADER_POSITION_WEIGHT_CAP_V1
|
||||
- TICK_NORMALIZER_V1
|
||||
- SELL_PRICE_SANITY_V1
|
||||
- PULLBACK_ENTRY_TRIGGER_V1
|
||||
- PROFIT_RATCHET_TIERED_V2
|
||||
- PROFIT_LOCK_STAGE_V1
|
||||
- STOP_PRICE_ADEQUACY_V1
|
||||
- POSITION_SIZE_REGIME_SCALE_V1
|
||||
- DRAWDOWN_GUARD_V1
|
||||
- CASH_RECOVERY_OPTIMIZER_V1
|
||||
- VALUE_PRESERVATION_SCORER_V1
|
||||
- VELOCITY_V1
|
||||
- ANTI_LATE_ENTRY_GATE_V2
|
||||
- ANTI_CHASING_VELOCITY_V1
|
||||
- POSITION_COUNT_LIMIT_V1
|
||||
- DYNAMIC_HEAT_GATE_V1
|
||||
- CASH_FLOOR_V1
|
||||
- REGIME_CASH_UPLIFT_V1
|
||||
- SEMICONDUCTOR_CLUSTER_GATE_V1
|
||||
- WIN_LOSS_STREAK_GUARD_V1
|
||||
- SINGLE_POSITION_WEIGHT_CAP_V1
|
||||
- REGIME_TRIM_GUIDANCE_V1
|
||||
- HEAT_CONCENTRATION_ALERT_V1
|
||||
- SECTOR_CONCENTRATION_LIMIT_V1
|
||||
- CASH_SHORTFALL_V1
|
||||
- K2_STAGED_REBOUND_SELL_V1
|
||||
- PORTFOLIO_DRAWDOWN_GATE_V1
|
||||
- PROFIT_LOCK_STAGE_V1
|
||||
- MARKET_WEIGHT_AWARE_CLUSTER_GATE_V1
|
||||
- LEADER_POSITION_WEIGHT_CAP_V1
|
||||
objective: '"formula_id 문자열이 .gs 텍스트에 등장한다" 는 문자열 커버리지(presence-based)를 폐기하고
|
||||
|
||||
# 산출 증빙 아티팩트
|
||||
evidence_artifacts:
|
||||
- Temp/formula_behavioral_coverage_v1.json
|
||||
- Temp/formula_gas_parity_v1.json
|
||||
"주어진 입력에 대해 golden(손계산 정답) == Python미러 == GAS미러 가 허용오차 내 일치한다"
|
||||
|
||||
# 완료 거부 조건 (Reject Conditions)
|
||||
reject_conditions:
|
||||
- "implementation_divergence_count > 0 인데 '완료' 선언"
|
||||
- "golden expected 값을 .gs 출력에서 역복사 (순환논리 — spec/13 expression에서 독립 계산해야 함)"
|
||||
- "예측 정확도를 '100% 달성'으로 서술 (truthfulness_guard 위반)"
|
||||
- "임계값·가격·수량을 LLM 추정으로 생성"
|
||||
는 행위기반 커버리지(behavioral coverage)로 전환한다.
|
||||
|
||||
# 명령어 목록 (저성능 LLM도 따라 실행 가능)
|
||||
구조적 거짓(결함 1)을 제거하기 위한 근본 측정 기반.
|
||||
|
||||
'
|
||||
ordered_commands:
|
||||
- id: B01
|
||||
command: "# 이 파일 생성 완료"
|
||||
expect: {file_exists: "spec/26_behavioral_coverage_contract.yaml"}
|
||||
- id: B02
|
||||
command: "# spec/formula_golden_cases_v2.yaml 작성"
|
||||
expect: {cases_total_min: 18, provenance: "HAND_COMPUTED or SPEC_DERIVED only"}
|
||||
- id: B03
|
||||
command: "python tools/run_formula_golden_cases_v2.py"
|
||||
expect: {python_fail: 0, output: "Temp/formula_behavioral_coverage_v1.json"}
|
||||
fail_code: BCH_PY_MIRROR_FAIL
|
||||
- id: B04
|
||||
command: "node tools/run_gas_golden_parity.js"
|
||||
expect: {gas_pass_min: 1, output: "Temp/formula_gas_parity_v1.json"}
|
||||
fail_code: BCH_GAS_PARITY_FAIL
|
||||
- id: B05
|
||||
command: "python tools/validate_behavioral_coverage_v1.py"
|
||||
expect:
|
||||
status_token: BEHAVIORAL_COVERAGE_V1_OK
|
||||
behavioral_coverage_pct: 100.0
|
||||
implementation_divergence_count: 0
|
||||
fail_code: BEHAVIORAL_COVERAGE_V1_FAIL
|
||||
- id: B06
|
||||
command: "# divergence 발견 시 spec/13 기준으로 GAS 또는 Python 수정"
|
||||
expect: {divergence_count: 0}
|
||||
fail_code: BCH_DIVERGENCE_OPEN
|
||||
- id: B07
|
||||
command: "npm run validate-behavioral-coverage"
|
||||
expect: {exit_code: 0}
|
||||
fail_code: BCH_WIRING_FAIL
|
||||
- command: '# 이 파일 생성 완료'
|
||||
expect:
|
||||
file_exists: spec/26_behavioral_coverage_contract.yaml
|
||||
id: B01
|
||||
- command: '# spec/formula_golden_cases_v2.yaml 작성'
|
||||
expect:
|
||||
cases_total_min: 18
|
||||
provenance: HAND_COMPUTED or SPEC_DERIVED only
|
||||
id: B02
|
||||
- command: python tools/run_formula_golden_cases_v2.py
|
||||
expect:
|
||||
output: Temp/formula_behavioral_coverage_v1.json
|
||||
python_fail: 0
|
||||
fail_code: BCH_PY_MIRROR_FAIL
|
||||
id: B03
|
||||
- command: node tools/run_gas_golden_parity.js
|
||||
expect:
|
||||
gas_pass_min: 1
|
||||
output: Temp/formula_gas_parity_v1.json
|
||||
fail_code: BCH_GAS_PARITY_FAIL
|
||||
id: B04
|
||||
- command: python tools/validate_behavioral_coverage_v1.py
|
||||
expect:
|
||||
behavioral_coverage_pct: 100.0
|
||||
implementation_divergence_count: 0
|
||||
status_token: BEHAVIORAL_COVERAGE_V1_OK
|
||||
fail_code: BEHAVIORAL_COVERAGE_V1_FAIL
|
||||
id: B05
|
||||
- command: '# divergence 발견 시 spec/13 기준으로 GAS 또는 Python 수정'
|
||||
expect:
|
||||
divergence_count: 0
|
||||
fail_code: BCH_DIVERGENCE_OPEN
|
||||
id: B06
|
||||
- command: npm run validate-behavioral-coverage
|
||||
expect:
|
||||
exit_code: 0
|
||||
fail_code: BCH_WIRING_FAIL
|
||||
id: B07
|
||||
reject_conditions:
|
||||
- implementation_divergence_count > 0 인데 '완료' 선언
|
||||
- golden expected 값을 .gs 출력에서 역복사 (순환논리 — spec/13 expression에서 독립 계산해야 함)
|
||||
- 예측 정확도를 '100% 달성'으로 서술 (truthfulness_guard 위반)
|
||||
- 임계값·가격·수량을 LLM 추정으로 생성
|
||||
three_way_gate:
|
||||
divergence_definition: 'python_output ≠ gas_output (허용오차 초과) 이면 IMPLEMENTATION_DIVERGENCE.
|
||||
|
||||
이는 "yaml 지침과 구현이 다른 숫자를 낸다"는 직접 증거이며 B06에서 근본 정정 필요.
|
||||
|
||||
'
|
||||
divergence_resolution: 'spec/13_formula_registry.yaml 의 expression이 기준.
|
||||
|
||||
GAS 또는 Python 중 spec에서 벗어난 쪽을 수정한다.
|
||||
|
||||
LLM 추정으로 수정 금지. spec expression 기계적 적용.
|
||||
|
||||
'
|
||||
gas_vs_golden_tolerance: 동일
|
||||
python_vs_golden_tolerance: 각 공식 케이스 yaml의 tolerance 필드 기준
|
||||
version: '2026-05-30'
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
|
||||
@@ -1,106 +1,99 @@
|
||||
schema_version: 2026-06-03-canonical-artifact-resolver-v2
|
||||
formula_id: CANONICAL_ARTIFACT_RESOLVER_V2
|
||||
supersedes: CANONICAL_ARTIFACT_RESOLVER_V1
|
||||
has_code_implementation: true
|
||||
code_path:
|
||||
- "tools/build_canonical_artifact_resolver_v1.py"
|
||||
- "tools/validate_canonical_artifact_resolver_v1.py"
|
||||
purpose: >
|
||||
산출물 단일 진실원장과 stale reference 차단.
|
||||
RC5 수정: 동일 개념의 다중 버전이 상호충돌·기술부채를 만든다.
|
||||
버전별 1개 canonical만 게이트 입력으로 허용.
|
||||
|
||||
# ── canonical 버전 맵 (개념별 최신·권위 버전 단일 지정) ─────────────────────
|
||||
acceptance_criteria:
|
||||
canonical_per_concept:
|
||||
note: 개념별 canonical == 1 (다중 권위본 0건)
|
||||
op: ==
|
||||
target: 1
|
||||
gate_input_canonical_pct:
|
||||
note: 게이트 입력 파일 100%가 canonical map에 존재
|
||||
op: ==
|
||||
target: 100
|
||||
canonical_source_precedence:
|
||||
- final_decision_packet_active
|
||||
- final_execution_decision_v4
|
||||
- smart_cash_recovery_v9
|
||||
- smart_cash_recovery_v8
|
||||
- engine_audit_v1
|
||||
- sell_engine_audit_v1
|
||||
canonical_versions:
|
||||
smart_cash_recovery:
|
||||
canonical: smart_cash_recovery_v9.json
|
||||
deprecated:
|
||||
- smart_cash_recovery_v8.json
|
||||
- smart_cash_recovery_v7.json
|
||||
- smart_cash_recovery_v6.json
|
||||
- smart_cash_recovery_v5.json
|
||||
- smart_cash_recovery_v4.json
|
||||
- smart_cash_recovery_v3.json
|
||||
gate_input_allowed: smart_cash_recovery_v9.json
|
||||
note: "v9부터 VALUE_PRESERVING_CASH_RAISE_V9 정책 적용 (BREACH_FULL_LIQUIDATION 금지)"
|
||||
|
||||
distribution_risk_score:
|
||||
canonical: distribution_risk_score_v4.json
|
||||
deprecated:
|
||||
- distribution_risk_score_v3.json
|
||||
- distribution_risk_score_v2.json
|
||||
gate_input_allowed: distribution_risk_score_v4.json
|
||||
|
||||
final_execution_decision:
|
||||
canonical: final_execution_decision_v4.json
|
||||
deprecated:
|
||||
- final_execution_decision_v3.json
|
||||
- final_execution_decision_v2.json
|
||||
- final_execution_decision_v1.json
|
||||
gate_input_allowed: final_execution_decision_v4.json
|
||||
|
||||
alpha_lead_threshold_optimizer:
|
||||
canonical: alpha_lead_threshold_optimizer_v3.json
|
||||
deprecated:
|
||||
- alpha_lead_threshold_optimizer_v2.json
|
||||
- alpha_lead_threshold_optimizer_v1.json
|
||||
- alpha_lead_threshold_optimizer_v2.json
|
||||
- alpha_lead_threshold_optimizer_v1.json
|
||||
gate_input_allowed: alpha_lead_threshold_optimizer_v3.json
|
||||
|
||||
pass_100_criteria:
|
||||
canonical: pass_100_criteria_v3.json
|
||||
deprecated:
|
||||
- pass_100_criteria_v2.json
|
||||
- pass_100_criteria_v1.json
|
||||
gate_input_allowed: pass_100_criteria_v3.json
|
||||
note: "v3에 RELEASE_GATE_TRUTH_V1 추가됨 (TASK-001)"
|
||||
|
||||
prediction_accuracy_harness:
|
||||
canonical: prediction_accuracy_harness_v5.json
|
||||
deprecated:
|
||||
- prediction_accuracy_harness_v4.json
|
||||
- prediction_accuracy_harness_v3.json
|
||||
- prediction_accuracy_harness_v2.json
|
||||
gate_input_allowed: prediction_accuracy_harness_v5.json
|
||||
|
||||
smart_money_liquidity_evidence_gate:
|
||||
canonical: smart_money_liquidity_evidence_gate_v5.json
|
||||
deprecated:
|
||||
- smart_money_liquidity_evidence_gate_v4.json
|
||||
- smart_money_liquidity_evidence_gate_v3.json
|
||||
- smart_money_liquidity_evidence_gate_v2.json
|
||||
gate_input_allowed: smart_money_liquidity_evidence_gate_v5.json
|
||||
|
||||
canonical_metrics:
|
||||
canonical: canonical_metrics_v4.json
|
||||
deprecated:
|
||||
- canonical_metrics_v3.json
|
||||
- canonical_metrics_v2.json
|
||||
- canonical_metrics_v1.json
|
||||
gate_input_allowed: canonical_metrics_v4.json
|
||||
|
||||
anti_late_entry_pullback_gate:
|
||||
canonical: anti_late_entry_pullback_gate_v4.json
|
||||
deprecated:
|
||||
- anti_late_entry_pullback_gate_v3.json
|
||||
- anti_late_entry_pullback_gate_v3.json
|
||||
gate_input_allowed: anti_late_entry_pullback_gate_v4.json
|
||||
canonical_metrics:
|
||||
canonical: canonical_metrics_v4.json
|
||||
deprecated:
|
||||
- canonical_metrics_v3.json
|
||||
- canonical_metrics_v2.json
|
||||
- canonical_metrics_v1.json
|
||||
gate_input_allowed: canonical_metrics_v4.json
|
||||
distribution_risk_score:
|
||||
canonical: distribution_risk_score_v4.json
|
||||
deprecated:
|
||||
- distribution_risk_score_v3.json
|
||||
- distribution_risk_score_v2.json
|
||||
gate_input_allowed: distribution_risk_score_v4.json
|
||||
final_execution_decision:
|
||||
canonical: final_execution_decision_v4.json
|
||||
deprecated:
|
||||
- final_execution_decision_v3.json
|
||||
- final_execution_decision_v2.json
|
||||
- final_execution_decision_v1.json
|
||||
gate_input_allowed: final_execution_decision_v4.json
|
||||
pass_100_criteria:
|
||||
canonical: pass_100_criteria_v3.json
|
||||
deprecated:
|
||||
- pass_100_criteria_v2.json
|
||||
- pass_100_criteria_v1.json
|
||||
gate_input_allowed: pass_100_criteria_v3.json
|
||||
note: v3에 RELEASE_GATE_TRUTH_V1 추가됨 (TASK-001)
|
||||
prediction_accuracy_harness:
|
||||
canonical: prediction_accuracy_harness_v5.json
|
||||
deprecated:
|
||||
- prediction_accuracy_harness_v4.json
|
||||
- prediction_accuracy_harness_v3.json
|
||||
- prediction_accuracy_harness_v2.json
|
||||
gate_input_allowed: prediction_accuracy_harness_v5.json
|
||||
smart_cash_recovery:
|
||||
canonical: smart_cash_recovery_v9.json
|
||||
deprecated:
|
||||
- smart_cash_recovery_v8.json
|
||||
- smart_cash_recovery_v7.json
|
||||
- smart_cash_recovery_v6.json
|
||||
- smart_cash_recovery_v5.json
|
||||
- smart_cash_recovery_v4.json
|
||||
- smart_cash_recovery_v3.json
|
||||
gate_input_allowed: smart_cash_recovery_v9.json
|
||||
note: v9부터 VALUE_PRESERVING_CASH_RAISE_V9 정책 적용 (BREACH_FULL_LIQUIDATION 금지)
|
||||
smart_money_liquidity_evidence_gate:
|
||||
canonical: smart_money_liquidity_evidence_gate_v5.json
|
||||
deprecated:
|
||||
- smart_money_liquidity_evidence_gate_v4.json
|
||||
- smart_money_liquidity_evidence_gate_v3.json
|
||||
- smart_money_liquidity_evidence_gate_v2.json
|
||||
gate_input_allowed: smart_money_liquidity_evidence_gate_v5.json
|
||||
code_path:
|
||||
- tools/build_canonical_artifact_resolver_v1.py
|
||||
- tools/validate_canonical_artifact_resolver_v1.py
|
||||
formula_id: CANONICAL_ARTIFACT_RESOLVER_V2
|
||||
has_code_implementation: true
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
purpose: '산출물 단일 진실원장과 stale reference 차단. RC5 수정: 동일 개념의 다중 버전이 상호충돌·기술부채를 만든다. 버전별
|
||||
1개 canonical만 게이트 입력으로 허용.
|
||||
|
||||
# ── 이전 단일 원천 우선순위 (하위호환 유지) ─────────────────────────────────
|
||||
canonical_source_precedence:
|
||||
- final_decision_packet_active
|
||||
- final_execution_decision_v4
|
||||
- smart_cash_recovery_v9
|
||||
- smart_cash_recovery_v8
|
||||
- engine_audit_v1
|
||||
- sell_engine_audit_v1
|
||||
|
||||
required_outputs:
|
||||
- canonical_metrics.cash_shortfall_min_krw
|
||||
- distinct_cash_shortfall_values
|
||||
- stale_artifact_reference_count
|
||||
|
||||
acceptance_criteria:
|
||||
canonical_per_concept: {op: "==", target: 1, note: "개념별 canonical == 1 (다중 권위본 0건)"}
|
||||
gate_input_canonical_pct: {op: "==", target: 100, note: "게이트 입력 파일 100%가 canonical map에 존재"}
|
||||
|
||||
'
|
||||
python_tool: tools/build_canonical_artifact_resolver_v1.py
|
||||
required_outputs:
|
||||
- canonical_metrics.cash_shortfall_min_krw
|
||||
- distinct_cash_shortfall_values
|
||||
- stale_artifact_reference_count
|
||||
schema_version: 2026-06-03-canonical-artifact-resolver-v2
|
||||
supersedes: CANONICAL_ARTIFACT_RESOLVER_V1
|
||||
validator: tools/validate_canonical_artifact_resolver_v1.py
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
schema_version: 2026-06-10-goal-risk-budget-harness-v2
|
||||
formula_id: GOAL_RISK_BUDGET_HARNESS_V2
|
||||
has_code_implementation: true
|
||||
code_path: "src/quant_engine/orchestration_harness_v1.py"
|
||||
purpose: 5억 목표와 리스크 예산/현금 방어선 연결. 매 릴리즈 drift 추적 포함.
|
||||
goal_target_krw: 500000000
|
||||
required_fields:
|
||||
- goal_achievement_pct
|
||||
- goal_remaining_krw
|
||||
- cash_defense_line_d2_used
|
||||
# P9-T03 추가: 성과 분해 필드
|
||||
- net_return_pct # 거래비용·슬리피지 제거 후 순수익률
|
||||
- gross_return_pct # 세전 총수익률
|
||||
- max_drawdown_pct # 최대낙폭 (운영 기간 전체)
|
||||
- hit_rate_pct # 매수 후 T+5 기준 수익 달성 비율
|
||||
- late_entry_loss_rate_pct # 추격매수 진입 후 손실 비율
|
||||
- profit_giveback_pct # 최고점 대비 이익 반납 비율
|
||||
# P9-T03 추가: drift 추적 필드
|
||||
- risk_budget_drift_pct # 이전 릴리즈 대비 MDD 예산 변화량
|
||||
- cash_defense_drift_krw # D+2 현금 방어선 이전 릴리즈 대비 변화량
|
||||
- goal_drift_months # 목표 달성 ETA 이전 릴리즈 대비 변화량(월)
|
||||
performance_decomposition_rules:
|
||||
- gross_return은 표시용으로만 사용. 사이징·게이트 판단은 net_return 기준.
|
||||
- max_drawdown 상한(20%)을 초과하면 신규 매수를 차단.
|
||||
- 목표 달성 압박을 이유로 MDD 상한·stop 규칙을 완화하는 것을 금지.
|
||||
- late_entry_loss_rate가 15%를 초과하면 anti-late-entry gate를 강화한다.
|
||||
- profit_giveback이 30%를 초과하면 trailing stop 파라미터를 조정한다.
|
||||
code_path: src/quant_engine/orchestration_harness_v1.py
|
||||
drift_gate:
|
||||
risk_budget_drift_max_pct: 2.0 # 단일 릴리즈에서 MDD 예산 ±2% 초과 시 경고
|
||||
cash_defense_drift_max_krw: 5000000 # 현금 방어선 500만원 이상 축소 시 경고
|
||||
goal_drift_months_max: 1 # ETA 1개월 이상 연장 시 경고
|
||||
cash_defense_drift_max_krw: 5000000
|
||||
goal_drift_months_max: 1
|
||||
risk_budget_drift_max_pct: 2.0
|
||||
formula_id: GOAL_RISK_BUDGET_HARNESS_V2
|
||||
goal_target_krw: 500000000
|
||||
has_code_implementation: true
|
||||
lifecycle_state: active
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
output_in_final_packet: true
|
||||
owner: risk_manager
|
||||
lifecycle_state: active
|
||||
performance_decomposition_rules:
|
||||
- gross_return은 표시용으로만 사용. 사이징·게이트 판단은 net_return 기준.
|
||||
- max_drawdown 상한(20%)을 초과하면 신규 매수를 차단.
|
||||
- 목표 달성 압박을 이유로 MDD 상한·stop 규칙을 완화하는 것을 금지.
|
||||
- late_entry_loss_rate가 15%를 초과하면 anti-late-entry gate를 강화한다.
|
||||
- profit_giveback이 30%를 초과하면 trailing stop 파라미터를 조정한다.
|
||||
purpose: 5억 목표와 리스크 예산/현금 방어선 연결. 매 릴리즈 drift 추적 포함.
|
||||
required_fields:
|
||||
- goal_achievement_pct
|
||||
- goal_remaining_krw
|
||||
- cash_defense_line_d2_used
|
||||
- net_return_pct
|
||||
- gross_return_pct
|
||||
- max_drawdown_pct
|
||||
- hit_rate_pct
|
||||
- late_entry_loss_rate_pct
|
||||
- profit_giveback_pct
|
||||
- risk_budget_drift_pct
|
||||
- cash_defense_drift_krw
|
||||
- goal_drift_months
|
||||
schema_version: 2026-06-10-goal-risk-budget-harness-v2
|
||||
updated_at: '2026-06-10T23:29:00+09:00'
|
||||
|
||||
@@ -1,60 +1,57 @@
|
||||
schema_version: evaluation_dashboard_contract.v2
|
||||
code_path: tools/build_continuous_evaluation_dashboard_v1.py
|
||||
formula_id: CONTINUOUS_EVALUATION_DASHBOARD_V1
|
||||
purpose: >
|
||||
P2-020: 주간 성과 대시보드. LIVE T+20 표본 기반 기대수익/승률/MDD/수익반납 지표 산출.
|
||||
REPLAY 표본은 informational 섹션에만 집계되며 성과 지표 계산에 혼입 금지.
|
||||
|
||||
python_tool: tools/build_continuous_evaluation_dashboard_v1.py
|
||||
has_code_implementation: true
|
||||
code_path: "tools/build_continuous_evaluation_dashboard_v1.py"
|
||||
sources:
|
||||
- Temp/proposal_evaluation_history.json
|
||||
output: Temp/continuous_evaluation_dashboard_v1.json
|
||||
|
||||
# -- 필수 필드 --
|
||||
required_fields:
|
||||
- weekly_scorecard_generated # bool: 주간 스코어카드 생성 여부
|
||||
- expectancy_pct # float: 평균 T+20 기대수익률 (LIVE만)
|
||||
- win_rate_pct # float: 수익 거래 비율 (T+20 > 0)
|
||||
- max_drawdown_pct # float: 단일 거래 최대 손실 (T+20 기준)
|
||||
- profit_giveback_pct # float: 수익의 50% 이상 반납 비율
|
||||
|
||||
# -- 지표 정의 --
|
||||
metric_definitions:
|
||||
expectancy_pct:
|
||||
formula: "mean(t20_return_pct) for LIVE EVALUATED_T20 records"
|
||||
target: "> 0"
|
||||
note: "T+20 표본이 30건 미만이면 INSUFFICIENT_DATA"
|
||||
win_rate_pct:
|
||||
formula: "count(t20_return_pct > 0) / count(EVALUATED_T20) * 100"
|
||||
target: ">= 50%"
|
||||
max_drawdown_pct:
|
||||
formula: "min(t20_return_pct) for EVALUATED_T20 records"
|
||||
note: "음수가 클수록 나쁨"
|
||||
profit_giveback_pct:
|
||||
formula: >
|
||||
count(proposals where t20_return > 0 AND subsequent outcome showed >50% giveback)
|
||||
/ count(profitable_t20) * 100
|
||||
note: "현재 giveback 추적 미구현 → None 반환"
|
||||
|
||||
# -- 주간 스코어카드 구조 --
|
||||
weekly_scorecard:
|
||||
group_by: ISO_week
|
||||
min_records_per_week: 3
|
||||
fields: [win_rate_pct, expectancy_pct, trade_count, avg_t20_days]
|
||||
|
||||
# -- gate 판정 --
|
||||
gate_logic:
|
||||
INSUFFICIENT_DATA:
|
||||
condition: "live_t20_count < 30"
|
||||
effect: "성과 지표를 None으로 표기 (게이트 실패 아님)"
|
||||
condition: live_t20_count < 30
|
||||
effect: 성과 지표를 None으로 표기 (게이트 실패 아님)
|
||||
PASS:
|
||||
condition: "live_t20_count >= 30"
|
||||
condition: live_t20_count >= 30
|
||||
WARNING:
|
||||
condition: "expectancy_pct < 0 OR win_rate_pct < 40"
|
||||
condition: expectancy_pct < 0 OR win_rate_pct < 40
|
||||
has_code_implementation: true
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
metric_definitions:
|
||||
expectancy_pct:
|
||||
formula: mean(t20_return_pct) for LIVE EVALUATED_T20 records
|
||||
note: T+20 표본이 30건 미만이면 INSUFFICIENT_DATA
|
||||
target: '> 0'
|
||||
max_drawdown_pct:
|
||||
formula: min(t20_return_pct) for EVALUATED_T20 records
|
||||
note: 음수가 클수록 나쁨
|
||||
profit_giveback_pct:
|
||||
formula: 'count(proposals where t20_return > 0 AND subsequent outcome showed >50%
|
||||
giveback) / count(profitable_t20) * 100
|
||||
|
||||
# -- 금지 사항 --
|
||||
'
|
||||
note: 현재 giveback 추적 미구현 → None 반환
|
||||
win_rate_pct:
|
||||
formula: count(t20_return_pct > 0) / count(EVALUATED_T20) * 100
|
||||
target: '>= 50%'
|
||||
output: Temp/continuous_evaluation_dashboard_v1.json
|
||||
prohibitions:
|
||||
- "REPLAY 표본을 성과 지표(win_rate/expectancy/MDD) 계산에 포함 금지"
|
||||
- "T+20 미확정 LIVE 거래를 EVALUATED_T20으로 분류 금지"
|
||||
- "외부 가격 데이터를 직접 조회해 T+20 수익률 계산 금지 (history 기록 기준만 사용)"
|
||||
- REPLAY 표본을 성과 지표(win_rate/expectancy/MDD) 계산에 포함 금지
|
||||
- T+20 미확정 LIVE 거래를 EVALUATED_T20으로 분류 금지
|
||||
- 외부 가격 데이터를 직접 조회해 T+20 수익률 계산 금지 (history 기록 기준만 사용)
|
||||
purpose: 'P2-020: 주간 성과 대시보드. LIVE T+20 표본 기반 기대수익/승률/MDD/수익반납 지표 산출. REPLAY 표본은 informational
|
||||
섹션에만 집계되며 성과 지표 계산에 혼입 금지.
|
||||
|
||||
'
|
||||
python_tool: tools/build_continuous_evaluation_dashboard_v1.py
|
||||
required_fields:
|
||||
- weekly_scorecard_generated
|
||||
- expectancy_pct
|
||||
- win_rate_pct
|
||||
- max_drawdown_pct
|
||||
- profit_giveback_pct
|
||||
schema_version: evaluation_dashboard_contract.v2
|
||||
sources:
|
||||
- Temp/proposal_evaluation_history.json
|
||||
weekly_scorecard:
|
||||
fields:
|
||||
- win_rate_pct
|
||||
- expectancy_pct
|
||||
- trade_count
|
||||
- avg_t20_days
|
||||
group_by: ISO_week
|
||||
min_records_per_week: 3
|
||||
|
||||
@@ -1,42 +1,45 @@
|
||||
schema_version: 2026-06-06-gas-thin-adapter-policy-v1
|
||||
policy_id: GAS_THIN_ADAPTER_POLICY_V1
|
||||
has_code_implementation: true
|
||||
code_path: "tools/validate_gas_thin_adapter_v1.py"
|
||||
purpose: >
|
||||
GAS에서 collect, normalize, export, display만 남기고 decision, sizing,
|
||||
stop_loss, take_profit, risk_score 로직은 Python으로 이전하기 위한 migration plan.
|
||||
allowed_responsibilities:
|
||||
- collect
|
||||
- normalize
|
||||
- export
|
||||
- display
|
||||
forbidden_responsibilities:
|
||||
- decision
|
||||
- sizing
|
||||
- stop_loss
|
||||
- take_profit
|
||||
- risk_score
|
||||
migration_plan:
|
||||
status: DONE
|
||||
phases:
|
||||
- phase: inventory
|
||||
status: DONE
|
||||
target: Temp/gas_business_logic_audit_v1.json
|
||||
action: 분류된 GAS 함수 목록을 확정한다.
|
||||
- phase: extract
|
||||
status: DONE
|
||||
target: tools/
|
||||
action: business_logic 함수를 Python compiler/stub layer로 이전한다.
|
||||
- phase: thin_adapter
|
||||
status: DONE
|
||||
target: gas_*.gs
|
||||
action: collect/normalize/export/display만 남기고 나머지를 호출 위임으로 전환한다.
|
||||
- phase: verify
|
||||
status: DONE
|
||||
target: tools/validate_gas_thin_adapter_v1.py
|
||||
action: forbidden_count가 줄어드는지 지속 검증한다.
|
||||
- collect
|
||||
- normalize
|
||||
- export
|
||||
- display
|
||||
code_path: tools/validate_gas_thin_adapter_v1.py
|
||||
exceptions:
|
||||
- name: runtime_report_rendering
|
||||
reason: 표 렌더링을 위한 문자열 포맷은 허용된다.
|
||||
- name: data_collection_helpers
|
||||
reason: 외부 JSON/시트 수집은 허용된다.
|
||||
- name: runtime_report_rendering
|
||||
reason: 표 렌더링을 위한 문자열 포맷은 허용된다.
|
||||
- name: data_collection_helpers
|
||||
reason: 외부 JSON/시트 수집은 허용된다.
|
||||
forbidden_responsibilities:
|
||||
- decision
|
||||
- sizing
|
||||
- stop_loss
|
||||
- take_profit
|
||||
- risk_score
|
||||
has_code_implementation: true
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
migration_plan:
|
||||
phases:
|
||||
- action: 분류된 GAS 함수 목록을 확정한다.
|
||||
phase: inventory
|
||||
status: DONE
|
||||
target: Temp/gas_business_logic_audit_v1.json
|
||||
- action: business_logic 함수를 Python compiler/stub layer로 이전한다.
|
||||
phase: extract
|
||||
status: DONE
|
||||
target: tools/
|
||||
- action: collect/normalize/export/display만 남기고 나머지를 호출 위임으로 전환한다.
|
||||
phase: thin_adapter
|
||||
status: DONE
|
||||
target: gas_*.gs
|
||||
- action: forbidden_count가 줄어드는지 지속 검증한다.
|
||||
phase: verify
|
||||
status: DONE
|
||||
target: tools/validate_gas_thin_adapter_v1.py
|
||||
status: DONE
|
||||
policy_id: GAS_THIN_ADAPTER_POLICY_V1
|
||||
purpose: 'GAS에서 collect, normalize, export, display만 남기고 decision, sizing, stop_loss,
|
||||
take_profit, risk_score 로직은 Python으로 이전하기 위한 migration plan.
|
||||
|
||||
'
|
||||
schema_version: 2026-06-06-gas-thin-adapter-policy-v1
|
||||
|
||||
+2385
-1666
File diff suppressed because it is too large
Load Diff
@@ -1,52 +1,50 @@
|
||||
schema_version: decision_trace_replay_contract.v1
|
||||
acceptance_criteria:
|
||||
- every_final_verdict_has_ordered_gate_trace: true
|
||||
- missing_gate_trace_blocks_release: true
|
||||
- verdict_replay_match_pct: 100.0
|
||||
authority: spec/52_decision_trace_replay_contract.yaml
|
||||
code_path: tools/validate_decision_trace_replay_v1.py
|
||||
contract_id: H001_DECISION_TRACE_REPLAY
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
hard_gates:
|
||||
- condition: all decisions have gate_trace length >= 1
|
||||
gate_id: TRACE_COMPLETE
|
||||
on_fail: BLOCK_RELEASE
|
||||
- condition: verdict_replay_match_pct == 100.0
|
||||
gate_id: VERDICT_REPLAY_MATCH
|
||||
on_fail: BLOCK_RELEASE
|
||||
harness_file: tools/validate_decision_trace_replay_v1.py
|
||||
has_code_implementation: true
|
||||
code_path: "tools/validate_decision_trace_replay_v1.py"
|
||||
authority: spec/52_decision_trace_replay_contract.yaml
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
purpose: >
|
||||
최종 매수/보유/매도 결론까지 사용된 모든 gate와 feature를 trace로 복원하여,
|
||||
결정의 재현성을 보장한다. 결론이 달라지는 trace 불일치는 릴리즈를 차단한다.
|
||||
|
||||
inputs:
|
||||
- field: final_decision_packet_active.json
|
||||
source: Temp/final_decision_packet_active.json
|
||||
required: true
|
||||
- field: computed_harness_v1.json
|
||||
source: Temp/computed_harness_v1.json
|
||||
required: true
|
||||
|
||||
output_fields:
|
||||
- name: gate_trace
|
||||
type: list[str]
|
||||
description: 결론까지 순서대로 통과한 gate ID 목록
|
||||
- name: feature_trace
|
||||
type: dict
|
||||
description: 결론에 사용된 feature key → value 맵
|
||||
- name: verdict_replay_match
|
||||
type: bool
|
||||
description: 재실행 시 최종 verdict가 동일한지 여부
|
||||
|
||||
acceptance_criteria:
|
||||
- every_final_verdict_has_ordered_gate_trace: true
|
||||
- missing_gate_trace_blocks_release: true
|
||||
- verdict_replay_match_pct: 100.0
|
||||
|
||||
hard_gates:
|
||||
- gate_id: TRACE_COMPLETE
|
||||
condition: all decisions have gate_trace length >= 1
|
||||
on_fail: BLOCK_RELEASE
|
||||
- gate_id: VERDICT_REPLAY_MATCH
|
||||
condition: verdict_replay_match_pct == 100.0
|
||||
on_fail: BLOCK_RELEASE
|
||||
|
||||
non_negotiable:
|
||||
- LLM은 gate_trace를 번복하거나 재해석하지 않는다
|
||||
- replay 시 동일 packet 입력이면 동일 결론을 내야 한다
|
||||
- trace가 없는 결론은 DATA_MISSING으로 표기하고 릴리즈를 차단한다
|
||||
|
||||
owner: quant_architect
|
||||
- field: final_decision_packet_active.json
|
||||
required: true
|
||||
source: Temp/final_decision_packet_active.json
|
||||
- field: computed_harness_v1.json
|
||||
required: true
|
||||
source: Temp/computed_harness_v1.json
|
||||
lifecycle_state: active
|
||||
retirement_condition: >
|
||||
대체 결정 추적 계약이 이 계약을 명시적으로 교체 선언할 때까지 유효하다.
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
non_negotiable:
|
||||
- LLM은 gate_trace를 번복하거나 재해석하지 않는다
|
||||
- replay 시 동일 packet 입력이면 동일 결론을 내야 한다
|
||||
- trace가 없는 결론은 DATA_MISSING으로 표기하고 릴리즈를 차단한다
|
||||
output_fields:
|
||||
- description: 결론까지 순서대로 통과한 gate ID 목록
|
||||
name: gate_trace
|
||||
type: list[str]
|
||||
- description: 결론에 사용된 feature key → value 맵
|
||||
name: feature_trace
|
||||
type: dict
|
||||
- description: 재실행 시 최종 verdict가 동일한지 여부
|
||||
name: verdict_replay_match
|
||||
type: bool
|
||||
owner: quant_architect
|
||||
purpose: '최종 매수/보유/매도 결론까지 사용된 모든 gate와 feature를 trace로 복원하여, 결정의 재현성을 보장한다. 결론이 달라지는
|
||||
trace 불일치는 릴리즈를 차단한다.
|
||||
|
||||
'
|
||||
retirement_condition: '대체 결정 추적 계약이 이 계약을 명시적으로 교체 선언할 때까지 유효하다.
|
||||
|
||||
'
|
||||
schema_version: decision_trace_replay_contract.v1
|
||||
|
||||
@@ -1,69 +1,68 @@
|
||||
schema_version: factor_conflict_matrix.v1
|
||||
acceptance_criteria:
|
||||
- conflict_precedence_defined_for_every_active_factor: true
|
||||
- unresolved_conflict_count: 0
|
||||
authority: spec/53_factor_conflict_matrix.yaml
|
||||
code_path: tools/validate_factor_conflict_matrix_v1.py
|
||||
conflict_precedence_rules:
|
||||
- family: portfolio_risk_budget
|
||||
rank: 1
|
||||
rationale: 현금방어선·MDD 상한은 어떤 alpha 신호보다 우선한다
|
||||
- family: execution_quality
|
||||
rank: 2
|
||||
rationale: 주문 불가 상태(틱 오류·현금 부족)는 매수/매도 모두 차단한다
|
||||
- family: entry_timing
|
||||
rank: 3
|
||||
rationale: 추격매수 방지 gate는 smart money 신호보다 우선한다
|
||||
- family: smart_money_liquidity
|
||||
rank: 4
|
||||
rationale: 외국인/기관 신호가 fundamental 신호보다 선행성이 높다
|
||||
- family: fundamental_quality
|
||||
rank: 5
|
||||
rationale: 장기 생존력 신호
|
||||
- family: market_regime
|
||||
rank: 6
|
||||
rationale: 거시 위험 판단으로 포지션 스케일 조정
|
||||
- family: exit_value_preservation
|
||||
rank: 7
|
||||
rationale: 수익금 보전 신호
|
||||
contract_id: H002_FACTOR_CONFLICT_MATRIX
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
hard_gates:
|
||||
- condition: unresolved_conflict_count == 0
|
||||
gate_id: CONFLICT_RESOLVED
|
||||
on_fail: BLOCK_RELEASE
|
||||
- condition: every active factor has conflict_precedence rank
|
||||
gate_id: PRECEDENCE_COMPLETE
|
||||
on_fail: BLOCK_RELEASE
|
||||
harness_file: tools/validate_factor_conflict_matrix_v1.py
|
||||
has_code_implementation: true
|
||||
code_path: "tools/validate_factor_conflict_matrix_v1.py"
|
||||
authority: spec/53_factor_conflict_matrix.yaml
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
purpose: >
|
||||
스마트머니/펀더멘털/모멘텀/리스크 팩터 충돌 시 우선순위를 자동으로 판정한다.
|
||||
미해결 충돌이 있으면 릴리즈를 차단한다.
|
||||
|
||||
conflict_precedence_rules:
|
||||
- rank: 1
|
||||
family: portfolio_risk_budget
|
||||
rationale: 현금방어선·MDD 상한은 어떤 alpha 신호보다 우선한다
|
||||
- rank: 2
|
||||
family: execution_quality
|
||||
rationale: 주문 불가 상태(틱 오류·현금 부족)는 매수/매도 모두 차단한다
|
||||
- rank: 3
|
||||
family: entry_timing
|
||||
rationale: 추격매수 방지 gate는 smart money 신호보다 우선한다
|
||||
- rank: 4
|
||||
family: smart_money_liquidity
|
||||
rationale: 외국인/기관 신호가 fundamental 신호보다 선행성이 높다
|
||||
- rank: 5
|
||||
family: fundamental_quality
|
||||
rationale: 장기 생존력 신호
|
||||
- rank: 6
|
||||
family: market_regime
|
||||
rationale: 거시 위험 판단으로 포지션 스케일 조정
|
||||
- rank: 7
|
||||
family: exit_value_preservation
|
||||
rationale: 수익금 보전 신호
|
||||
|
||||
inputs:
|
||||
- field: factor_lifecycle_registry.yaml
|
||||
source: spec/factor_lifecycle_registry.yaml
|
||||
required: true
|
||||
- field: final_decision_packet_active.json
|
||||
source: Temp/final_decision_packet_active.json
|
||||
required: true
|
||||
|
||||
output_fields:
|
||||
- name: conflict_matrix
|
||||
type: list[dict]
|
||||
description: 충돌 팩터 쌍과 우선순위 결과
|
||||
- name: unresolved_conflict_count
|
||||
type: int
|
||||
description: 우선순위 미정의 충돌 수
|
||||
- name: gate
|
||||
type: str
|
||||
enum: [PASS, FAIL]
|
||||
|
||||
acceptance_criteria:
|
||||
- conflict_precedence_defined_for_every_active_factor: true
|
||||
- unresolved_conflict_count: 0
|
||||
|
||||
hard_gates:
|
||||
- gate_id: CONFLICT_RESOLVED
|
||||
condition: unresolved_conflict_count == 0
|
||||
on_fail: BLOCK_RELEASE
|
||||
- gate_id: PRECEDENCE_COMPLETE
|
||||
condition: every active factor has conflict_precedence rank
|
||||
on_fail: BLOCK_RELEASE
|
||||
|
||||
owner: quant_architect
|
||||
- field: factor_lifecycle_registry.yaml
|
||||
required: true
|
||||
source: spec/factor_lifecycle_registry.yaml
|
||||
- field: final_decision_packet_active.json
|
||||
required: true
|
||||
source: Temp/final_decision_packet_active.json
|
||||
lifecycle_state: active
|
||||
retirement_condition: >
|
||||
팩터 충돌 해소 체계를 전면 재설계하는 계약이 등장할 때까지 유효하다.
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
output_fields:
|
||||
- description: 충돌 팩터 쌍과 우선순위 결과
|
||||
name: conflict_matrix
|
||||
type: list[dict]
|
||||
- description: 우선순위 미정의 충돌 수
|
||||
name: unresolved_conflict_count
|
||||
type: int
|
||||
- enum:
|
||||
- PASS
|
||||
- FAIL
|
||||
name: gate
|
||||
type: str
|
||||
owner: quant_architect
|
||||
purpose: '스마트머니/펀더멘털/모멘텀/리스크 팩터 충돌 시 우선순위를 자동으로 판정한다. 미해결 충돌이 있으면 릴리즈를 차단한다.
|
||||
|
||||
'
|
||||
retirement_condition: '팩터 충돌 해소 체계를 전면 재설계하는 계약이 등장할 때까지 유효하다.
|
||||
|
||||
'
|
||||
schema_version: factor_conflict_matrix.v1
|
||||
|
||||
@@ -1,61 +1,62 @@
|
||||
schema_version: temporal_data_integrity.v1
|
||||
contract_id: H003_ANTI_BACKFILL_LOOKAHEAD
|
||||
harness_file: tools/validate_no_lookahead_bias_v1.py
|
||||
has_code_implementation: true
|
||||
code_path: "tools/validate_no_lookahead_bias_v1.py"
|
||||
authority: spec/54_temporal_data_integrity.yaml
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
purpose: >
|
||||
백필 데이터와 실시간 데이터의 timestamp/freshness 혼입을 차단한다.
|
||||
feature_timestamp가 decision_timestamp를 초과하는 lookahead는 즉시 차단한다.
|
||||
|
||||
definitions:
|
||||
lookahead_bias: >
|
||||
feature 계산에 사용된 데이터의 as_of_date가
|
||||
해당 결정이 내려진 decision_timestamp보다 미래인 경우
|
||||
backfill_contamination: >
|
||||
과거 결정 평가 시 그 시점에 없던 데이터가 소급 적용된 경우
|
||||
|
||||
inputs:
|
||||
- field: computed_harness_v1.json
|
||||
source: Temp/computed_harness_v1.json
|
||||
required: true
|
||||
- field: GatherTradingData.json
|
||||
source: GatherTradingData.json
|
||||
required: true
|
||||
|
||||
output_fields:
|
||||
- name: lookahead_violation_count
|
||||
type: int
|
||||
description: feature_timestamp > decision_timestamp 건수
|
||||
- name: backfilled_after_decision_count
|
||||
type: int
|
||||
description: 결정 이후 소급 backfill된 데이터 건수
|
||||
- name: freshness_violation_tickers
|
||||
type: list[str]
|
||||
description: freshness 위반 종목 목록
|
||||
- name: gate
|
||||
type: str
|
||||
enum: [PASS, FAIL]
|
||||
|
||||
acceptance_criteria:
|
||||
- feature_timestamp_lte_decision_timestamp: true
|
||||
- backfilled_after_decision_count: 0
|
||||
|
||||
hard_gates:
|
||||
- gate_id: NO_LOOKAHEAD
|
||||
condition: lookahead_violation_count == 0
|
||||
on_fail: BLOCK_RELEASE
|
||||
- gate_id: NO_BACKFILL_CONTAMINATION
|
||||
condition: backfilled_after_decision_count == 0
|
||||
on_fail: BLOCK_RELEASE
|
||||
|
||||
- feature_timestamp_lte_decision_timestamp: true
|
||||
- backfilled_after_decision_count: 0
|
||||
authority: spec/54_temporal_data_integrity.yaml
|
||||
code_path: tools/validate_no_lookahead_bias_v1.py
|
||||
contract_id: H003_ANTI_BACKFILL_LOOKAHEAD
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
data_freshness_sla:
|
||||
price_data_max_age_hours: 1
|
||||
fundamental_data_max_age_days: 30
|
||||
macro_data_max_age_hours: 24
|
||||
price_data_max_age_hours: 1
|
||||
definitions:
|
||||
backfill_contamination: '과거 결정 평가 시 그 시점에 없던 데이터가 소급 적용된 경우
|
||||
|
||||
owner: data_engineer
|
||||
'
|
||||
lookahead_bias: 'feature 계산에 사용된 데이터의 as_of_date가 해당 결정이 내려진 decision_timestamp보다
|
||||
미래인 경우
|
||||
|
||||
'
|
||||
hard_gates:
|
||||
- condition: lookahead_violation_count == 0
|
||||
gate_id: NO_LOOKAHEAD
|
||||
on_fail: BLOCK_RELEASE
|
||||
- condition: backfilled_after_decision_count == 0
|
||||
gate_id: NO_BACKFILL_CONTAMINATION
|
||||
on_fail: BLOCK_RELEASE
|
||||
harness_file: tools/validate_no_lookahead_bias_v1.py
|
||||
has_code_implementation: true
|
||||
inputs:
|
||||
- field: computed_harness_v1.json
|
||||
required: true
|
||||
source: Temp/computed_harness_v1.json
|
||||
- field: GatherTradingData.json
|
||||
required: true
|
||||
source: GatherTradingData.json
|
||||
lifecycle_state: active
|
||||
retirement_condition: >
|
||||
실시간 스트리밍 파이프라인으로 전환 시 해당 파이프라인 계약으로 교체한다.
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
output_fields:
|
||||
- description: feature_timestamp > decision_timestamp 건수
|
||||
name: lookahead_violation_count
|
||||
type: int
|
||||
- description: 결정 이후 소급 backfill된 데이터 건수
|
||||
name: backfilled_after_decision_count
|
||||
type: int
|
||||
- description: freshness 위반 종목 목록
|
||||
name: freshness_violation_tickers
|
||||
type: list[str]
|
||||
- enum:
|
||||
- PASS
|
||||
- FAIL
|
||||
name: gate
|
||||
type: str
|
||||
owner: data_engineer
|
||||
purpose: '백필 데이터와 실시간 데이터의 timestamp/freshness 혼입을 차단한다. feature_timestamp가 decision_timestamp를
|
||||
초과하는 lookahead는 즉시 차단한다.
|
||||
|
||||
'
|
||||
retirement_condition: '실시간 스트리밍 파이프라인으로 전환 시 해당 파이프라인 계약으로 교체한다.
|
||||
|
||||
'
|
||||
schema_version: temporal_data_integrity.v1
|
||||
|
||||
@@ -1,74 +1,73 @@
|
||||
schema_version: execution_simulator_contract.v1
|
||||
contract_id: H004_EXECUTION_SIMULATOR
|
||||
harness_file: tools/validate_execution_simulator_v1.py
|
||||
acceptance_criteria:
|
||||
- invalid_order_count: 0
|
||||
- cash_floor_after_orders_krw_gte_required: true
|
||||
authority: spec/55_execution_simulator_contract.yaml
|
||||
has_code_implementation: true
|
||||
code_path: "tools/validate_execution_simulator_v1.py"
|
||||
code_path: tools/validate_execution_simulator_v1.py
|
||||
contract_id: H004_EXECUTION_SIMULATOR
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
purpose: >
|
||||
틱 정규화, 최소주문수량, 예수금, D+2 현금, 슬리피지 적용 후
|
||||
실제 주문 가능성을 검증한다. 유효하지 않은 주문이 단 1건이라도
|
||||
hard_gates:
|
||||
- condition: invalid_order_count == 0
|
||||
gate_id: NO_INVALID_ORDERS
|
||||
on_fail: BLOCK_RELEASE
|
||||
- condition: cash_floor_after_orders_krw >= minimum_reserve_krw
|
||||
gate_id: CASH_FLOOR_MAINTAINED
|
||||
on_fail: BLOCK_RELEASE
|
||||
- condition: all order prices are tick-normalized
|
||||
gate_id: TICK_NORMALIZED
|
||||
on_fail: BLOCK_RELEASE
|
||||
harness_file: tools/validate_execution_simulator_v1.py
|
||||
has_code_implementation: true
|
||||
inputs:
|
||||
- field: final_decision_packet_active.json
|
||||
required: true
|
||||
source: Temp/final_decision_packet_active.json
|
||||
- field: account_snapshot
|
||||
required: true
|
||||
source: spec/15_account_snapshot_contract.yaml
|
||||
lifecycle_state: active
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
output_fields:
|
||||
- description: 틱·수량·현금 조건 위반 주문 수
|
||||
name: invalid_order_count
|
||||
type: int
|
||||
- description: 모든 매수 주문 실행 후 예상 잔여 현금
|
||||
name: cash_floor_after_orders_krw
|
||||
type: float
|
||||
- description: 슬리피지 반영 후 최종 주문 목록
|
||||
name: slippage_adjusted_orders
|
||||
type: list[dict]
|
||||
- enum:
|
||||
- PASS
|
||||
- FAIL
|
||||
name: gate
|
||||
type: str
|
||||
owner: risk_manager
|
||||
purpose: '틱 정규화, 최소주문수량, 예수금, D+2 현금, 슬리피지 적용 후 실제 주문 가능성을 검증한다. 유효하지 않은 주문이 단 1건이라도
|
||||
있으면 릴리즈를 차단한다.
|
||||
|
||||
'
|
||||
retirement_condition: '실제 증권사 API 연동 시뮬레이터로 교체될 때까지 유효하다.
|
||||
|
||||
'
|
||||
schema_version: execution_simulator_contract.v1
|
||||
simulation_parameters:
|
||||
tick_normalization:
|
||||
rule: 가격은 해당 종목의 호가단위(tick size)로 내림하여 정규화
|
||||
source: spec/13_formula_registry.yaml → TICK_NORMALIZATION_V1
|
||||
minimum_order_quantity:
|
||||
krx_stock: 1주
|
||||
etf: 1주
|
||||
slippage_model:
|
||||
type: fixed_spread
|
||||
bps: calibration_registry.EXECUTION_SLIPPAGE_BPS
|
||||
note: >
|
||||
시장가 주문 기준 평균 슬리피지. WBS-7.6(2026-06-22)에서
|
||||
spec/calibration_registry.yaml의 EXECUTION_SLIPPAGE_BPS(5bps, EXPERT_PRIOR)로
|
||||
정규화. 실측 거래 데이터 20건 이상 누적 후 actual_slippage 추적해
|
||||
필요시 보정 (차이 > 1bps 시).
|
||||
cash_floor:
|
||||
d_plus_2_recognition: true
|
||||
minimum_reserve_krw: 10000000
|
||||
note: D+2 결제 예정 현금은 즉시 가용 현금으로 인정하되, 매수 후 잔여 현금이 최소 준비금 미만이면 차단
|
||||
goal_target_krw: 500000000
|
||||
minimum_order_quantity:
|
||||
etf: 1주
|
||||
krx_stock: 1주
|
||||
slippage_model:
|
||||
bps: calibration_registry.EXECUTION_SLIPPAGE_BPS
|
||||
note: '시장가 주문 기준 평균 슬리피지. WBS-7.6(2026-06-22)에서 spec/calibration_registry.yaml의
|
||||
EXECUTION_SLIPPAGE_BPS(5bps, EXPERT_PRIOR)로 정규화. 실측 거래 데이터 20건 이상 누적 후 actual_slippage
|
||||
추적해 필요시 보정 (차이 > 1bps 시).
|
||||
|
||||
inputs:
|
||||
- field: final_decision_packet_active.json
|
||||
source: Temp/final_decision_packet_active.json
|
||||
required: true
|
||||
- field: account_snapshot
|
||||
source: spec/15_account_snapshot_contract.yaml
|
||||
required: true
|
||||
|
||||
output_fields:
|
||||
- name: invalid_order_count
|
||||
type: int
|
||||
description: 틱·수량·현금 조건 위반 주문 수
|
||||
- name: cash_floor_after_orders_krw
|
||||
type: float
|
||||
description: 모든 매수 주문 실행 후 예상 잔여 현금
|
||||
- name: slippage_adjusted_orders
|
||||
type: list[dict]
|
||||
description: 슬리피지 반영 후 최종 주문 목록
|
||||
- name: gate
|
||||
type: str
|
||||
enum: [PASS, FAIL]
|
||||
|
||||
acceptance_criteria:
|
||||
- invalid_order_count: 0
|
||||
- cash_floor_after_orders_krw_gte_required: true
|
||||
|
||||
hard_gates:
|
||||
- gate_id: NO_INVALID_ORDERS
|
||||
condition: invalid_order_count == 0
|
||||
on_fail: BLOCK_RELEASE
|
||||
- gate_id: CASH_FLOOR_MAINTAINED
|
||||
condition: cash_floor_after_orders_krw >= minimum_reserve_krw
|
||||
on_fail: BLOCK_RELEASE
|
||||
- gate_id: TICK_NORMALIZED
|
||||
condition: all order prices are tick-normalized
|
||||
on_fail: BLOCK_RELEASE
|
||||
|
||||
owner: risk_manager
|
||||
lifecycle_state: active
|
||||
retirement_condition: >
|
||||
실제 증권사 API 연동 시뮬레이터로 교체될 때까지 유효하다.
|
||||
'
|
||||
type: fixed_spread
|
||||
tick_normalization:
|
||||
rule: 가격은 해당 종목의 호가단위(tick size)로 내림하여 정규화
|
||||
source: spec/13_formula_registry.yaml → TICK_NORMALIZATION_V1
|
||||
|
||||
@@ -1,72 +1,70 @@
|
||||
schema_version: renderer_copy_only_contract.v1
|
||||
acceptance_criteria:
|
||||
- numeric_diff_count: 0
|
||||
- narrative_softening_count: 0
|
||||
authority: spec/56_renderer_copy_only_contract.yaml
|
||||
code_path: tools/validate_report_render_diff_v1.py
|
||||
contract_id: H005_REPORT_RENDER_DIFF
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
forbidden_patterns:
|
||||
- description: 렌더러가 계산을 수행하는 표현
|
||||
pattern: .*계산.*하면.*
|
||||
- description: 렌더러가 평균을 계산하는 표현
|
||||
pattern: .*평균을 내면.*
|
||||
- description: 렌더러가 합산을 수행하는 표현
|
||||
pattern: .*합산하면.*
|
||||
- description: 렌더러가 값을 추정하는 표현
|
||||
pattern: .*추정.*하면.*
|
||||
hard_gates:
|
||||
- condition: numeric_diff_count == 0
|
||||
gate_id: NUMERIC_SYNC
|
||||
on_fail: BLOCK_RELEASE
|
||||
- condition: narrative_softening_count == 0
|
||||
gate_id: NO_NARRATIVE_SOFTENING
|
||||
on_fail: BLOCK_RELEASE
|
||||
harness_file: tools/validate_report_render_diff_v1.py
|
||||
has_code_implementation: true
|
||||
code_path: "tools/validate_report_render_diff_v1.py"
|
||||
authority: spec/56_renderer_copy_only_contract.yaml
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
purpose: >
|
||||
operational_report.md/json의 숫자가 final_decision_packet과 1:1 복사인지 검증한다.
|
||||
LLM이 보고서 생성 과정에서 어떠한 계산도 수행하지 않았음을 보장한다.
|
||||
F08(display_text) 계열은 이 계약의 렌더링 전용 유지 근거를 따른다.
|
||||
|
||||
renderer_rules:
|
||||
- LLM은 packet에서 이미 계산된 값을 copy-only로 렌더링한다
|
||||
- 수량/가격/비중/점수/순위/평균/합계 계산을 하지 않는다
|
||||
- 값이 없으면 'DATA_MISSING — 하네스 업데이트 필요'로만 표기한다
|
||||
- blocked/limited 종목도 산출된 기준가·손절가·익절가·수량을 숨기지 않는다
|
||||
- 투자 결론은 final_execution_decision과 gate_trace를 번복하지 않는다
|
||||
- 매도 후보가 2개 이상이면 sell priority table을 먼저 출력한다
|
||||
- narrative는 gate를 완화하거나 회피하는 표현을 쓰지 않는다
|
||||
|
||||
forbidden_patterns:
|
||||
- pattern: ".*계산.*하면.*"
|
||||
description: 렌더러가 계산을 수행하는 표현
|
||||
- pattern: ".*평균을 내면.*"
|
||||
description: 렌더러가 평균을 계산하는 표현
|
||||
- pattern: ".*합산하면.*"
|
||||
description: 렌더러가 합산을 수행하는 표현
|
||||
- pattern: ".*추정.*하면.*"
|
||||
description: 렌더러가 값을 추정하는 표현
|
||||
|
||||
inputs:
|
||||
- field: final_decision_packet_active.json
|
||||
source: Temp/final_decision_packet_active.json
|
||||
required: true
|
||||
- field: operational_report.json
|
||||
source: Temp/operational_report.json
|
||||
required: true
|
||||
- field: operational_report.md
|
||||
source: Temp/operational_report.md
|
||||
required: false
|
||||
|
||||
output_fields:
|
||||
- name: numeric_diff_count
|
||||
type: int
|
||||
description: 패킷과 보고서 간 숫자 불일치 건수
|
||||
- name: narrative_softening_count
|
||||
type: int
|
||||
description: gate를 완화하는 내러티브 표현 건수
|
||||
- name: forbidden_phrase_count
|
||||
type: int
|
||||
description: 금지 패턴 감지 건수
|
||||
- name: gate
|
||||
type: str
|
||||
enum: [PASS, FAIL]
|
||||
|
||||
acceptance_criteria:
|
||||
- numeric_diff_count: 0
|
||||
- narrative_softening_count: 0
|
||||
|
||||
hard_gates:
|
||||
- gate_id: NUMERIC_SYNC
|
||||
condition: numeric_diff_count == 0
|
||||
on_fail: BLOCK_RELEASE
|
||||
- gate_id: NO_NARRATIVE_SOFTENING
|
||||
condition: narrative_softening_count == 0
|
||||
on_fail: BLOCK_RELEASE
|
||||
|
||||
owner: pm
|
||||
- field: final_decision_packet_active.json
|
||||
required: true
|
||||
source: Temp/final_decision_packet_active.json
|
||||
- field: operational_report.json
|
||||
required: true
|
||||
source: Temp/operational_report.json
|
||||
- field: operational_report.md
|
||||
required: false
|
||||
source: Temp/operational_report.md
|
||||
lifecycle_state: active
|
||||
retirement_condition: >
|
||||
보고서 생성 파이프라인이 전면 재설계될 때까지 유효하다.
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
output_fields:
|
||||
- description: 패킷과 보고서 간 숫자 불일치 건수
|
||||
name: numeric_diff_count
|
||||
type: int
|
||||
- description: gate를 완화하는 내러티브 표현 건수
|
||||
name: narrative_softening_count
|
||||
type: int
|
||||
- description: 금지 패턴 감지 건수
|
||||
name: forbidden_phrase_count
|
||||
type: int
|
||||
- enum:
|
||||
- PASS
|
||||
- FAIL
|
||||
name: gate
|
||||
type: str
|
||||
owner: pm
|
||||
purpose: 'operational_report.md/json의 숫자가 final_decision_packet과 1:1 복사인지 검증한다. LLM이
|
||||
보고서 생성 과정에서 어떠한 계산도 수행하지 않았음을 보장한다. F08(display_text) 계열은 이 계약의 렌더링 전용 유지 근거를 따른다.
|
||||
|
||||
'
|
||||
renderer_rules:
|
||||
- LLM은 packet에서 이미 계산된 값을 copy-only로 렌더링한다
|
||||
- 수량/가격/비중/점수/순위/평균/합계 계산을 하지 않는다
|
||||
- 값이 없으면 'DATA_MISSING — 하네스 업데이트 필요'로만 표기한다
|
||||
- blocked/limited 종목도 산출된 기준가·손절가·익절가·수량을 숨기지 않는다
|
||||
- 투자 결론은 final_execution_decision과 gate_trace를 번복하지 않는다
|
||||
- 매도 후보가 2개 이상이면 sell priority table을 먼저 출력한다
|
||||
- narrative는 gate를 완화하거나 회피하는 표현을 쓰지 않는다
|
||||
retirement_condition: '보고서 생성 파이프라인이 전면 재설계될 때까지 유효하다.
|
||||
|
||||
'
|
||||
schema_version: renderer_copy_only_contract.v1
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
schema_version: shadow_promotion_scorecard.v1
|
||||
acceptance_criteria:
|
||||
- live_sample_count_gte_30: true
|
||||
- edge_improvement_positive: true
|
||||
- drawdown_not_worse: true
|
||||
- conflict_rate_within_cap: true
|
||||
authority: spec/57_shadow_promotion_scorecard.yaml
|
||||
code_path: tools/build_shadow_promotion_scorecard_v1.py
|
||||
contract_id: H007_SHADOW_PROMOTION_SCORECARD
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
forbidden_promotion_shortcuts:
|
||||
- replay 성과를 live 성과로 혼용하여 승격 기준 달성 금지
|
||||
- shadow 단계를 건너뛰고 바로 active 승격 금지
|
||||
- LLM narrative로 promotion gate 완화 금지
|
||||
- live_sample_count < 30인 팩터에 PASS_100 등급 부여 금지
|
||||
harness_file: tools/build_shadow_promotion_scorecard_v1.py
|
||||
has_code_implementation: true
|
||||
code_path: "tools/build_shadow_promotion_scorecard_v1.py"
|
||||
authority: spec/57_shadow_promotion_scorecard.yaml
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
purpose: >
|
||||
신규 팩터를 active로 올릴지 수치로 판단한다.
|
||||
live 표본 30개 미만, 또는 drawdown 악화, 또는 conflict 비율 초과 시
|
||||
active 승격을 차단한다.
|
||||
|
||||
inputs:
|
||||
- field: shadow_ledger_v2.json
|
||||
required: true
|
||||
source: Temp/shadow_ledger_v2.json
|
||||
- field: live_replay_separation_v3.json
|
||||
required: true
|
||||
source: Temp/live_replay_separation_v3.json
|
||||
lifecycle_state: active
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
output_fields:
|
||||
- description: 승격 가능 팩터 목록 (live_sample >= 30 and all gates pass)
|
||||
name: promotion_candidates
|
||||
type: list[dict]
|
||||
- description: 승격 차단 팩터 목록과 차단 사유
|
||||
name: blocked_factors
|
||||
type: list[dict]
|
||||
- enum:
|
||||
- PASS
|
||||
- FAIL
|
||||
- WARN
|
||||
name: gate
|
||||
type: str
|
||||
owner: quant_researcher
|
||||
promotion_gate_criteria:
|
||||
live_sample_count_minimum: 30
|
||||
conflict_rate_cap:
|
||||
max_conflict_rate_pct: 10.0
|
||||
note: 다른 active 팩터와 충돌하는 신호 비율
|
||||
drawdown_constraint:
|
||||
rule: 신규 팩터 적용 후 portfolio max drawdown이 기존 대비 악화되지 않아야 한다
|
||||
tolerance_pct: 0.5
|
||||
edge_improvement:
|
||||
metric: prediction_match_rate_improvement
|
||||
minimum_delta_pct: 2.0
|
||||
note: replay 표본은 포함하지 않는다. live 표본만 집계한다.
|
||||
drawdown_constraint:
|
||||
rule: 신규 팩터 적용 후 portfolio max drawdown이 기존 대비 악화되지 않아야 한다
|
||||
tolerance_pct: 0.5
|
||||
false_positive_reduction:
|
||||
minimum_reduction_pct: 5.0
|
||||
note: false positive = 매수 추천했으나 T+5 기준 손실 발생 건
|
||||
conflict_rate_cap:
|
||||
max_conflict_rate_pct: 10.0
|
||||
note: 다른 active 팩터와 충돌하는 신호 비율
|
||||
live_sample_count_minimum: 30
|
||||
provenance_coverage:
|
||||
required_pct: 100.0
|
||||
purpose: '신규 팩터를 active로 올릴지 수치로 판단한다. live 표본 30개 미만, 또는 drawdown 악화, 또는 conflict
|
||||
비율 초과 시 active 승격을 차단한다.
|
||||
|
||||
forbidden_promotion_shortcuts:
|
||||
- replay 성과를 live 성과로 혼용하여 승격 기준 달성 금지
|
||||
- shadow 단계를 건너뛰고 바로 active 승격 금지
|
||||
- LLM narrative로 promotion gate 완화 금지
|
||||
- live_sample_count < 30인 팩터에 PASS_100 등급 부여 금지
|
||||
'
|
||||
retirement_condition: '팩터 승격 체계를 전면 재설계하는 계약이 등장할 때까지 유효하다.
|
||||
|
||||
inputs:
|
||||
- field: shadow_ledger_v2.json
|
||||
source: Temp/shadow_ledger_v2.json
|
||||
required: true
|
||||
- field: live_replay_separation_v3.json
|
||||
source: Temp/live_replay_separation_v3.json
|
||||
required: true
|
||||
|
||||
output_fields:
|
||||
- name: promotion_candidates
|
||||
type: list[dict]
|
||||
description: 승격 가능 팩터 목록 (live_sample >= 30 and all gates pass)
|
||||
- name: blocked_factors
|
||||
type: list[dict]
|
||||
description: 승격 차단 팩터 목록과 차단 사유
|
||||
- name: gate
|
||||
type: str
|
||||
enum: [PASS, FAIL, WARN]
|
||||
|
||||
acceptance_criteria:
|
||||
- live_sample_count_gte_30: true
|
||||
- edge_improvement_positive: true
|
||||
- drawdown_not_worse: true
|
||||
- conflict_rate_within_cap: true
|
||||
|
||||
owner: quant_researcher
|
||||
lifecycle_state: active
|
||||
retirement_condition: >
|
||||
팩터 승격 체계를 전면 재설계하는 계약이 등장할 때까지 유효하다.
|
||||
'
|
||||
schema_version: shadow_promotion_scorecard.v1
|
||||
|
||||
@@ -1,82 +1,111 @@
|
||||
schema_version: llm_determinism_contract.v1
|
||||
acceptance_criteria:
|
||||
- all_decision_fields_precomputed: true
|
||||
- all_tables_sorted_in_packet: true
|
||||
- no_instruction_requires_arithmetic: true
|
||||
authority: spec/58_llm_determinism_contract.yaml
|
||||
code_path: tools/validate_llm_determinism_pack_v1.py
|
||||
contract_id: H008_LLM_DETERMINISM_AUDIT
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
hard_gates:
|
||||
- condition: arithmetic_instruction_count == 0
|
||||
gate_id: NO_ARITHMETIC_INSTRUCTION
|
||||
on_fail: BLOCK_RELEASE
|
||||
- condition: missing_sections == []
|
||||
gate_id: ALL_SECTIONS_PRESENT
|
||||
on_fail: BLOCK_RELEASE
|
||||
- condition: precomputed_field_coverage_pct == 100.0
|
||||
gate_id: PRECOMPUTED_COVERAGE
|
||||
on_fail: BLOCK_RELEASE
|
||||
harness_file: tools/validate_llm_determinism_pack_v1.py
|
||||
has_code_implementation: true
|
||||
code_path: "tools/validate_llm_determinism_pack_v1.py"
|
||||
authority: spec/58_llm_determinism_contract.yaml
|
||||
created_at: '2026-06-10T23:29:00+09:00'
|
||||
purpose: >
|
||||
저성능 LLM도 packet copy-only로 같은 결과를 렌더링할 만큼
|
||||
final_context_for_llm이 충분히 사전 계산되어 있는지 검증한다.
|
||||
LLM에게 산술 연산을 요구하는 항목이 있으면 릴리즈를 차단한다.
|
||||
|
||||
required_precomputed_sections:
|
||||
- section: 01_metadata_and_manifest_alias
|
||||
must_contain: [document_id, generated_at_kst, active_artifact_alias]
|
||||
- section: 02_portfolio_health
|
||||
must_contain: [total_asset_krw, cash_ratio_pct, goal_achievement_pct]
|
||||
- section: 03_hard_blockers
|
||||
must_contain: [blocked_tickers, blocker_reasons]
|
||||
- section: 04_sell_priority_table
|
||||
must_contain: [rank, ticker, sell_action, sell_reason_code]
|
||||
note: 이미 정렬된 순서로 제공. LLM은 재정렬하지 않는다.
|
||||
- section: 05_buy_hold_sell_action_table
|
||||
must_contain: [ticker, final_action, entry_price, stop_price, quantity]
|
||||
- section: 06_cash_and_risk_budget
|
||||
must_contain: [available_cash_krw, d2_cash_krw, max_allowed_mdd_pct]
|
||||
- section: 07_shadow_ledger_visible_items
|
||||
must_contain: [formula_id, lifecycle_state, sample_n, promotion_allowed]
|
||||
- section: 08_data_missing_items
|
||||
must_contain: [missing_field, reason]
|
||||
- section: 09_market_regime_summary_precomputed
|
||||
must_contain: [regime_label, regime_score, position_scale_factor]
|
||||
- section: 10_education_notes_preapproved
|
||||
note: 사전 승인된 교육 노트만 포함. LLM이 신규 작성 금지.
|
||||
- section: 11_forbidden_phrases_and_no_math_rules
|
||||
must_contain: [forbidden_phrases, no_math_rule]
|
||||
|
||||
validation_rules:
|
||||
- all_numeric_fields_precomputed: true
|
||||
- all_tables_pre_sorted: true
|
||||
- no_arithmetic_instruction_in_prompt: true
|
||||
- llm_numeric_generation_count: 0
|
||||
|
||||
inputs:
|
||||
- field: final_context_for_llm_v5.yaml
|
||||
source: Temp/final_context_for_llm_v5.yaml
|
||||
required: true
|
||||
|
||||
output_fields:
|
||||
- name: missing_sections
|
||||
type: list[str]
|
||||
description: 누락된 required section 목록
|
||||
- name: arithmetic_instruction_count
|
||||
type: int
|
||||
description: LLM에게 계산을 요구하는 지시 건수
|
||||
- name: precomputed_field_coverage_pct
|
||||
type: float
|
||||
description: 사전 계산된 필드 비율
|
||||
- name: gate
|
||||
type: str
|
||||
enum: [PASS, FAIL]
|
||||
|
||||
acceptance_criteria:
|
||||
- all_decision_fields_precomputed: true
|
||||
- all_tables_sorted_in_packet: true
|
||||
- no_instruction_requires_arithmetic: true
|
||||
|
||||
hard_gates:
|
||||
- gate_id: NO_ARITHMETIC_INSTRUCTION
|
||||
condition: arithmetic_instruction_count == 0
|
||||
on_fail: BLOCK_RELEASE
|
||||
- gate_id: ALL_SECTIONS_PRESENT
|
||||
condition: missing_sections == []
|
||||
on_fail: BLOCK_RELEASE
|
||||
- gate_id: PRECOMPUTED_COVERAGE
|
||||
condition: precomputed_field_coverage_pct == 100.0
|
||||
on_fail: BLOCK_RELEASE
|
||||
|
||||
owner: pm
|
||||
- field: final_context_for_llm_v5.yaml
|
||||
required: true
|
||||
source: Temp/final_context_for_llm_v5.yaml
|
||||
lifecycle_state: active
|
||||
retirement_condition: >
|
||||
LLM 파이프라인이 완전 결정론적 서버 사이드 렌더링으로 교체될 때까지 유효하다.
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
output_fields:
|
||||
- description: 누락된 required section 목록
|
||||
name: missing_sections
|
||||
type: list[str]
|
||||
- description: LLM에게 계산을 요구하는 지시 건수
|
||||
name: arithmetic_instruction_count
|
||||
type: int
|
||||
- description: 사전 계산된 필드 비율
|
||||
name: precomputed_field_coverage_pct
|
||||
type: float
|
||||
- enum:
|
||||
- PASS
|
||||
- FAIL
|
||||
name: gate
|
||||
type: str
|
||||
owner: pm
|
||||
purpose: '저성능 LLM도 packet copy-only로 같은 결과를 렌더링할 만큼 final_context_for_llm이 충분히 사전
|
||||
계산되어 있는지 검증한다. LLM에게 산술 연산을 요구하는 항목이 있으면 릴리즈를 차단한다.
|
||||
|
||||
'
|
||||
required_precomputed_sections:
|
||||
- must_contain:
|
||||
- document_id
|
||||
- generated_at_kst
|
||||
- active_artifact_alias
|
||||
section: 01_metadata_and_manifest_alias
|
||||
- must_contain:
|
||||
- total_asset_krw
|
||||
- cash_ratio_pct
|
||||
- goal_achievement_pct
|
||||
section: 02_portfolio_health
|
||||
- must_contain:
|
||||
- blocked_tickers
|
||||
- blocker_reasons
|
||||
section: 03_hard_blockers
|
||||
- must_contain:
|
||||
- rank
|
||||
- ticker
|
||||
- sell_action
|
||||
- sell_reason_code
|
||||
note: 이미 정렬된 순서로 제공. LLM은 재정렬하지 않는다.
|
||||
section: 04_sell_priority_table
|
||||
- must_contain:
|
||||
- ticker
|
||||
- final_action
|
||||
- entry_price
|
||||
- stop_price
|
||||
- quantity
|
||||
section: 05_buy_hold_sell_action_table
|
||||
- must_contain:
|
||||
- available_cash_krw
|
||||
- d2_cash_krw
|
||||
- max_allowed_mdd_pct
|
||||
section: 06_cash_and_risk_budget
|
||||
- must_contain:
|
||||
- formula_id
|
||||
- lifecycle_state
|
||||
- sample_n
|
||||
- promotion_allowed
|
||||
section: 07_shadow_ledger_visible_items
|
||||
- must_contain:
|
||||
- missing_field
|
||||
- reason
|
||||
section: 08_data_missing_items
|
||||
- must_contain:
|
||||
- regime_label
|
||||
- regime_score
|
||||
- position_scale_factor
|
||||
section: 09_market_regime_summary_precomputed
|
||||
- note: 사전 승인된 교육 노트만 포함. LLM이 신규 작성 금지.
|
||||
section: 10_education_notes_preapproved
|
||||
- must_contain:
|
||||
- forbidden_phrases
|
||||
- no_math_rule
|
||||
section: 11_forbidden_phrases_and_no_math_rules
|
||||
retirement_condition: 'LLM 파이프라인이 완전 결정론적 서버 사이드 렌더링으로 교체될 때까지 유효하다.
|
||||
|
||||
'
|
||||
schema_version: llm_determinism_contract.v1
|
||||
validation_rules:
|
||||
- all_numeric_fields_precomputed: true
|
||||
- all_tables_pre_sorted: true
|
||||
- no_arithmetic_instruction_in_prompt: true
|
||||
- llm_numeric_generation_count: 0
|
||||
|
||||
+11
-24
@@ -1,26 +1,13 @@
|
||||
meta:
|
||||
title: "은퇴자산포트폴리오 — 경로 alias registry"
|
||||
version: "2026-06-21-WBS7.4_migration_closed"
|
||||
role: "governance"
|
||||
purpose: "legacy path와 canonical split path를 명시해 참조 혼선을 방지한다."
|
||||
|
||||
# 2026-06-21 WBS-7.4 마이그레이션 종결 기록:
|
||||
# 아래 17개 alias는 모두 remove_after=2026-06-30 만료 예정이었다.
|
||||
# repo 전체(spec/src/tools/prompts/examples) grep으로 활성 참조가 0건임을 확인했고,
|
||||
# 모든 canonical_split_files 대상 파일이 이미 실콘텐츠를 보유하고 있어 마이그레이션이
|
||||
# 완료된 것으로 판정, 데드라인 전에 alias 항목을 제거했다.
|
||||
#
|
||||
# [2026-06-22 WBS-7.11 정정] 작성 당시 이 주석은 호환 인덱스 5개 중 "3개가
|
||||
# deprecated_redirect라 삭제 보류 중"이라고 적었으나 부정확했다. 실제로는
|
||||
# spec/06_exit_policy.yaml도 role: compatibility_index(영구 유지 설계)였고,
|
||||
# role: deprecated_redirect는 spec/03_risk_policy.yaml, spec/04_strategy_rules.yaml
|
||||
# 2개뿐이었다. WBS-7.11에서 이 2개의 활성 참조 0건을 재확인 후 실삭제했고,
|
||||
# spec/06_exit_policy.yaml/spec/risk/risk_control.yaml/spec/strategy/entry_gates.yaml
|
||||
# 3개는 has_code_implementation:false + redirect_only:true로 태깅해 영구 유지한다.
|
||||
aliases: {}
|
||||
|
||||
meta:
|
||||
has_code_implementation: false
|
||||
purpose: legacy path와 canonical split path를 명시해 참조 혼선을 방지한다.
|
||||
role: governance
|
||||
title: 은퇴자산포트폴리오 — 경로 alias registry
|
||||
version: 2026-06-21-WBS7.4_migration_closed
|
||||
policy:
|
||||
- "신규 문서는 canonical 경로만 사용한다."
|
||||
- "compatibility index와 aliases.yaml 내부의 deprecated 경로는 허용한다."
|
||||
- "remove_after 이후 deprecated 경로가 active 문서에 남으면 검증 실패로 전환한다."
|
||||
- "alias 항목을 등록할 때는 반드시 remove_after 데드라인을 두고, 데드라인 전에 활성 참조 0건을 확인한 뒤 제거한다(2026-06-21 사례 참조)."
|
||||
- 신규 문서는 canonical 경로만 사용한다.
|
||||
- compatibility index와 aliases.yaml 내부의 deprecated 경로는 허용한다.
|
||||
- remove_after 이후 deprecated 경로가 active 문서에 남으면 검증 실패로 전환한다.
|
||||
- alias 항목을 등록할 때는 반드시 remove_after 데드라인을 두고, 데드라인 전에 활성 참조 0건을 확인한 뒤 제거한다(2026-06-21
|
||||
사례 참조).
|
||||
|
||||
+1914
-1917
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user