diff --git a/src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs b/src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs index 2e166f2..7274497 100644 --- a/src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs +++ b/src/gas_adapter_parts/gdc_01_fetch_fundamentals.gs @@ -2242,7 +2242,15 @@ function runDataFeed() { const macroSheet = getSpreadsheet_().getSheetByName("macro"); if (macroSheet) { const mData = macroSheet.getDataRange().getValues(); - const mHdr = mData[1] ?? []; + let headerRowIdx = 0; + for (let r = 0; r < Math.min(5, mData.length); r++) { + const row = mData[r] ?? []; + if (row.indexOf("Symbol") >= 0 && row.indexOf("Name") >= 0) { + headerRowIdx = r; + break; + } + } + const mHdr = mData[headerRowIdx] ?? []; const symIdx = mHdr.indexOf("Symbol"); const nameIdx = mHdr.indexOf("Name"); const closeIdx = mHdr.indexOf("Close"); @@ -2251,7 +2259,7 @@ function runDataFeed() { const ret10DIdx = mHdr.indexOf("Ret10D"); const ret20DIdx = mHdr.indexOf("Ret20D"); const ret60DIdx = mHdr.indexOf("Ret60D"); - for (let i = 2; i < mData.length; i++) { + for (let i = headerRowIdx + 1; i < mData.length; i++) { const sym = symIdx >= 0 ? String(mData[i][symIdx]).trim() : ""; const name = nameIdx >= 0 ? String(mData[i][nameIdx]).trim() : ""; if (name === "KOSPI") { diff --git a/tools/validate_live_data_activation_gate_v1.py b/tools/validate_live_data_activation_gate_v1.py index 5ac2fc7..5526112 100644 --- a/tools/validate_live_data_activation_gate_v1.py +++ b/tools/validate_live_data_activation_gate_v1.py @@ -124,7 +124,7 @@ def run() -> dict: "target_date": ACTIVATION_DATE_TARGET, "message": ( f"live_t20={live_t20_count}/{LIVE_T20_THRESHOLD} " - f"({progress_pct}%) — 목표일 {ACTIVATION_DATE_TARGET}까지 " + f"({progress_pct}%) - 목표일 {ACTIVATION_DATE_TARGET}까지 " f"{days_remaining}일 잔여" ), "transition_checks": [], @@ -141,14 +141,14 @@ def run() -> dict: "progress_pct": 100.0, "message": ( f"live_t20 임계값 도달({live_t20_count}건). " - f"전환 조건 {'전부 PASS' if all_pass else '일부 FAIL — 재빌드 필요'}." + f"전환 조건 {'전부 PASS' if all_pass else '일부 FAIL - 재빌드 필요'}." ), "transition_checks": transition_checks, "all_transitions_complete": all_pass, } OUTPUT_PATH.parent.mkdir(parents=True, exist_ok=True) - OUTPUT_PATH.write_text(json.dumps(result, ensure_ascii=False, indent=2)) + OUTPUT_PATH.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") return result @@ -160,7 +160,7 @@ def main() -> None: if gate == "FAIL": failed = [c for c in result.get("transition_checks", []) if not c["passed"]] for f in failed: - print(f" FAIL: {f['condition']} — actual={f['actual']} target={f['target']}") + print(f" FAIL: {f['condition']} - actual={f['actual']} target={f['target']}") sys.exit(1) if gate == "PENDING": sys.exit(0) # PENDING은 오류가 아님, 정상 진행 중