schema_version: gas_logic_migration_ledger.v1
source: governance/gas_logic_migration_ledger_v1.yaml
authored: 2026-06-10
total_findings: 15
classification_summary:
  decision_logic: 4
  score_logic: 5
  price_qty_logic: 4
  pure_mapping: 1
  display_text: 1
unclassified_findings: 0

# Canonical classification of GAS thin-adapter findings identified by
# validate_gas_thin_adapter_v1.py. Each finding is classified by what type
# of logic it contains and paired with a migration_action.
findings:
  - id: F01
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 186
    text: "SP_TAKE_PROFIT:        10,  // Profit_Pct >= 10% (익절 후보)"
    classification: score_logic
    migration_action: REGISTER_SP_TAKE_PROFIT
    target_file: formulas/score_thresholds_v1.py
    status: TODO

  - id: F02
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 656
    text: "priceBasis = Number.isFinite(tp2Price) ? \"TAKE_PROFIT_TIER2_PRICE\" : \"PRIOR_CLOSE_X_0.998\";"
    classification: price_qty_logic
    migration_action: MIGRATE_PRICEBASIS_TO_PYTHON
    target_file: formulas/price_basis_v1.py
    status: TODO
    blocking_on: F03 F04 (same function, migrate together)

  - id: F03
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 665
    text: "priceBasis = Number.isFinite(tp2Price) ? \"TAKE_PROFIT_TIER2_PRICE\" : \"PRIOR_CLOSE_X_0.998\";"
    classification: price_qty_logic
    migration_action: MIGRATE_PRICEBASIS_TO_PYTHON
    target_file: formulas/price_basis_v1.py
    status: TODO
    blocking_on: F02 F04

  - id: F04
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 674
    text: "priceBasis = Number.isFinite(tp1Price) ? \"TAKE_PROFIT_TIER1_PRICE\" : \"PRIOR_CLOSE_X_0.998\";"
    classification: price_qty_logic
    migration_action: MIGRATE_PRICEBASIS_TO_PYTHON
    target_file: formulas/price_basis_v1.py
    status: TODO

  - id: F05
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 678
    text: "action = \"TAKE_PROFIT_TIER1\";"
    classification: decision_logic
    migration_action: MIGRATE_DECISIONS_ROUTING
    target_file: formulas/execution_decision_v1.py
    status: TODO

  - id: F06
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 683
    text: "priceBasis = Number.isFinite(tp1Price) ? \"TAKE_PROFIT_TIER1_PRICE\" : \"PRIOR_CLOSE_X_0.998\";"
    classification: price_qty_logic
    migration_action: MIGRATE_PRICEBASIS_TO_PYTHON
    target_file: formulas/price_basis_v1.py
    status: TODO

  - id: F07
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 1577
    text: "score += THRESHOLDS[\"SP_TAKE_PROFIT\"];"
    classification: score_logic
    migration_action: MIGRATE_SCORE_CALCULATION
    target_file: formulas/score_thresholds_v1.py
    status: TODO

  - id: F08
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 1578
    text: "breakdown.push(`take_profit:+${THRESHOLDS[\"SP_TAKE_PROFIT\"]}`)"
    classification: display_text
    migration_action: DISPLAY_TEXT_PASSTHROUGH
    notes: display_text stays in GAS adapter as rendering concern
    status: KEEP_IN_GAS

  - id: F09
    file: src/gas_adapter_parts/gdf_01_price_metrics.gs
    line: 2164
    text: "TAKE_PROFIT_BASE:    10,"
    classification: score_logic
    migration_action: REGISTER_TAKE_PROFIT_BASE
    target_file: formulas/score_thresholds_v1.py
    status: TODO

  - id: F10
    file: src/gas_adapter_parts/gdf_03_portfolio_gates.gs
    line: 1335
    text: "return { [\"decisions\"]: routes, traces: traces, lock: true };"
    classification: decision_logic
    migration_action: MIGRATE_DECISIONS_ROUTING
    target_file: formulas/routing_decision_v1.py
    status: TODO

  - id: F11
    file: src/gas_adapter_parts/gdf_03_portfolio_gates.gs
    line: 1360
    text: "if (holding && holding.stopBreach) return 'STOP_LOSS';"
    classification: decision_logic
    migration_action: MIGRATE_STOP_BREACH_DECISION
    target_file: formulas/stop_loss_gate_v1.py
    status: TODO

  - id: F12
    file: src/gas_adapter_parts/gdf_03_portfolio_gates.gs
    line: 2128
    text: "[\"distribution_risk_score\"]: Math.min(100, Math.max(0, score)),"
    classification: score_logic
    migration_action: DELETE_DISTRIBUTION_RISK_GAS
    target_file: formulas/distribution_risk_v1.py
    status: TODO
    notes: Python canonical (build_distribution_risk_v1.py) already exists; GAS version is duplicate

  - id: F13
    file: src/gas_adapter_parts/gdf_03_portfolio_gates.gs
    line: 2132
    text: "formula_id: 'DISTRIBUTION_RISK_SCORE_V1'"
    classification: pure_mapping
    migration_action: DELETE_DISTRIBUTION_RISK_GAS
    status: TODO
    notes: formula_id tag stays with Python canonical; remove from GAS

  - id: F14
    file: src/gas_adapter_parts/gdf_03_portfolio_gates.gs
    line: 2214
    text: "[\"late_chase_risk_score\"]: Math.min(100, Math.max(0, Math.round(lateChaseRisk))),"
    classification: score_logic
    migration_action: DELETE_LATE_CHASE_RISK_GAS
    target_file: formulas/late_chase_risk_v1.py
    status: TODO
    notes: Python canonical (build_alpha_lead_table_v1.py) computes late_chase_risk; GAS version is duplicate

  - id: F15
    file: src/gas_adapter_parts/gdf_04_execution_quality.gs
    line: 479
    text: "if (bqRow.breakout_quality_gate === 'BLOCKED_LATE_CHASE' || alphaRow[\"late_chase_risk_score\"] >= 70)"
    classification: decision_logic
    migration_action: MIGRATE_LATE_CHASE_GATE
    target_file: formulas/late_chase_gate_v1.py
    status: TODO

# Migration action summary (9 actions)
migration_actions:
  - action_id: REGISTER_SP_TAKE_PROFIT
    findings: [F01]
    description: Register SP_TAKE_PROFIT threshold (value=10) in Python score_thresholds canonical
    priority: LOW

  - action_id: REGISTER_TAKE_PROFIT_BASE
    findings: [F09]
    description: Register TAKE_PROFIT_BASE threshold (value=10) in Python score_thresholds canonical
    priority: LOW

  - action_id: DELETE_DISTRIBUTION_RISK_GAS
    findings: [F12, F13]
    description: Remove distribution_risk_score calculation from gdf_03; Python canonical exists
    priority: HIGH
    blocker: verify build_distribution_risk_v1.py output matches GAS output before delete

  - action_id: DELETE_LATE_CHASE_RISK_GAS
    findings: [F14]
    description: Remove late_chase_risk_score from gdf_03; Python canonical in alpha_lead_table_v1
    priority: HIGH
    blocker: verify parity before delete

  - action_id: MIGRATE_PRICEBASIS_TO_PYTHON
    findings: [F02, F03, F04, F06]
    description: priceBasis string selection (TIER1/TIER2 or PRIOR_CLOSE_X_0.998) → Python canonical
    priority: MEDIUM

  - action_id: MIGRATE_SCORE_CALCULATION
    findings: [F07]
    description: score += THRESHOLDS["SP_TAKE_PROFIT"] pattern → Python canonical scorer
    priority: MEDIUM

  - action_id: MIGRATE_STOP_BREACH_DECISION
    findings: [F11]
    description: holding.stopBreach → STOP_LOSS decision → Python canonical stop_loss_gate
    priority: HIGH
    notes: critical path — must match validate_stop_loss_policy_v1 spec

  - action_id: MIGRATE_DECISIONS_ROUTING
    findings: [F05, F10]
    description: TAKE_PROFIT_TIER1 action assignment and routing lock decision → Python canonical
    priority: MEDIUM

  - action_id: MIGRATE_LATE_CHASE_GATE
    findings: [F15]
    description: BLOCKED_LATE_CHASE gate check (threshold 70) → Python canonical gate formula
    priority: HIGH
    blocker: late_chase_risk_score must come from Python before GAS gate can be removed
