virtual-insanity
← 리포트 목록

석유 공급망 크론 정상화

2026-04-14 oil [openclaw, cron, oil, energy, commodity, ops]

석유 공급망 크론 정상화 최종 보고

결론

  • ~/.openclaw/cron/jobs.json에서 키워드 기준 관련 크론 24개 확인.
  • 실제 운영 대상 12개 + disabled 1개(petrochemical-report)의 실행 페이로드 정리.
  • oil-supply-monitor-afternoon 실패의 직접 원인은 정상 스크립트 크론 옆에 켜져 있던 main/systemEvent 중복 리마인더와, 일부 agentTurn payload가 message 대신 command/text를 써서 스크립트를 실행하지 못한 문제로 확인.
  • Telegram 전달 누락/등급 문제는 관련 스크립트 알림을 level="info"로 명시하고, Telegram 메타가 남아있는 크론은 chatId=492860021, to="492860021"를 갖도록 정리.
  • EIA 3지표 수집기는 feedgas 1개 소스 실패가 전체 exit 1로 번지던 문제를 격리. primary feedgas 예외 시 fallback을 시도하고, 한 지표 실패가 나머지 DUC/rig 수집을 막지 않도록 변경.
  • shared/llm.py는 건드리지 않음.

찾은 관련 크론

키워드: oil, petrol, energy, supply, copper, metal, commodity, 석유, 에너지, crude, gas, lng

활성 운영 크론

id 목적 현재 상태 스크립트
upstream-tracker 업스트림 에너지 지표 enabled upstream_tracker.py
tanker-tracker 탱커/LNG 해운 지표 enabled tanker_tracker.py
collect-cluster 반도체+석유화학 통합 수집 enabled semiconductor_cycle_tracker.py, petrochemical_cycle_tracker.py
oil-supply-monitor 글로벌 석유 공급망 모니터 enabled oil_supply_monitor.py
oil-supply-monitor-afternoon 오후 14시 석유 공급망 모니터 enabled oil_supply_monitor.py
oil-supply-monitor-evening 저녁 21시 석유 공급망 모니터 enabled oil_supply_monitor.py
energy-data-collector EIA/에너지 지표 수집 enabled energy_data_collector.py
commodity-spike-morning 원자재 급변 아침 분석 enabled commodity_spike_analyzer.py --mode morning
commodity-spike-watch 원자재 실시간 감시 enabled commodity_spike_analyzer.py --mode watch
cu-fnguide-snapshot FnGuide 컨센서스 스냅샷 enabled fnguide_snapshot.py
copper-market-collector 구리 선물 커브/SHFE 재고 enabled copper_market_collector.py
eia-energy-3indicators EIA 에너지 방법론 3지표 enabled eia_energy_collector.py

비활성 또는 직접 수정 제외

id 상태 판단
petrochemical-report disabled 비활성 상태 유지. payload만 실제 report 스크립트 명령 형태로 정리됨.
cowork-full enabled 프롬프트 본문에 키워드가 들어가 hit 됐지만 광범위 새벽 심층 분석 크론이라 에너지 크론으로 직접 수정하지 않음.
ea53641b-..., 3bd314bb-..., be1c48a1-..., cf3eb52d-..., 32e3abac-..., 97ce225f-..., 4b1295b3-..., 550368d5-..., 3b87597b-..., 0cc8a0ae-... disabled oil-supply-monitor-* main/systemEvent 중복 리마인더. 실제 스크립트 실행이 아니라 LLM 리마인더만 주입해 혼선을 만들던 항목이라 비활성 유지.

최근 로그에서 확인한 실패 패턴

  • oil-supply-monitor-afternoon: “무엇을 도와드릴까요?”, “작업을 등록할까요?” 같은 응답 반복. 즉 스크립트 실행이 아니라 크론 생성/수정 질문으로 해석됨.
  • 3b87597b-be7e-4e05-a21b-8520ede11539: cron: job execution timed out, duration 약 600초. 정상 스크립트가 아니라 systemEvent 리마인더가 오래 물고 있던 케이스.
  • commodity-spike-watch, eia-energy-3indicators: 과거 run log에 “현재 크론 잡 상태 확인/새 크론 추가/즉시 실행 중 골라 달라” 식 응답. payload.message 누락 또는 text/command 경로 때문에 실제 Bash 실행이 안 된 증거.
  • tanker-tracker, upstream-tracker: “아래 명령을 Bash로 실행하라”는 문장이 결과 summary로만 저장된 기록이 있음. 이후 질문하지 말고 명시 지시와 payload.message로 정규화.
  • 과거 알림 오류: Delivering to Telegram requires target <chatId>, Channel is required... 패턴 확인. 현재 활성 관련 크론의 Telegram delivery 누락은 0건.

수정한 파일과 변경 라인

/Users/ron/.openclaw/cron/jobs.json

백업: - /Users/ron/.openclaw/cron/jobs.json.bak.oil-cron-fix-1776129204614 - /Users/ron/.openclaw/cron/jobs.json.bak.oil-cron-restart-1776130375621

주요 변경: - 관련 agentTurn payload를 payload.message 기반의 명시적 Bash 실행 지시로 정규화. - payload.command/payload.text 제거. - 실제 스크립트 크론은 sessionTarget="isolated", payload.kind="agentTurn", delivery.mode="none"로 정리. - oil 3개 모니터는 payload.timeoutSeconds=900 유지/확인. - Telegram delivery 메타가 남아있는 관련 크론에는 chatId=492860021, to="492860021" 보강. - 중복 oil main/systemEvent 리마인더 10개 비활성화.

주요 라인: - petrochemical-report: 909 - upstream-tracker: 1857 - tanker-tracker: 1890 - collect-cluster: 2473 - oil-supply-monitor: 2778 - oil-supply-monitor-afternoon: 2830 - oil-supply-monitor-evening: 2865 - energy-data-collector: 4250 - commodity-spike-morning: 4763 - commodity-spike-watch: 4800 - cu-fnguide-snapshot: 4871 - copper-market-collector: 5007 - eia-energy-3indicators: 5110 - 비활성화된 oil 중복 리마인더: 7587, 7785, 7862, 8019, 8116, 8290, 8832, 9666, 9857, 9896

/Users/ron/.openclaw/workspace/scripts/pipeline/copper_market_collector.py

  • line 362: send_dm(msg)send_dm(msg, level="info")
  • 근거: Telegram 등급 게이트 정책상 루틴/정보성 알림은 INFO 경로로 명시.

/Users/ron/.openclaw/workspace/scripts/pipeline/commodity_spike_analyzer.py

  • line 470: send_dm(msg, level="alert")send_dm(msg, level="info")
  • 근거: alert도 shared gateway에서 INFO로 취급되지만, 원자재 루틴 크론은 DM 격상 없이 알림센터 경로가 맞으므로 명시값을 info로 통일.

/Users/ron/.openclaw/workspace/scripts/pipeline/eia_energy_collector.py

  • line 294: feedgas primary N9133US2 예외 시 fallback 시도하도록 변경.
  • line 537: _safe_collect() 추가. feedgas/DUC/rig 중 하나가 예외를 내도 전체 수집이 exit 1로 종료되지 않게 격리.
  • line 617: send_dm(msg, level="alert")send_dm(msg, level="info")
  • 근거: EIA API/DNS/소스 장애는 특정 지표 실패로 기록하고 나머지 지표를 계속 처리해야 함.

회귀 테스트

  • /Users/ron/.openclaw/workspace/tests/test_oil_energy_crons.py
  • line 61: 관련 크론이 실제 pipeline script를 payload.message로 실행하는지 검증.
  • line 81: Telegram delivery 메타가 있으면 chatId/to가 있는지 검증.
  • line 96: oil main/systemEvent 중복 리마인더가 다시 켜지지 않는지 검증.
  • line 117: 관련 스크립트 알림이 level="info"를 쓰는지 검증.
  • /Users/ron/.openclaw/workspace/tests/test_eia_energy_collector_resilience.py
  • line 23: EIA 한 소스가 예외를 내도 다른 지표가 계속 수집되는지 검증.
  • line 48: feedgas primary 소스 예외 시 fallback이 사용되는지 검증.

데이터 소스 확인과 대체 소스

  • Feedgas/LNG export primary: EIA API v2 route natural-gas/move/expc, series N9133US2.
  • Feedgas fallback: shared.eia_client.get_ng_feedgas_demand(), route natural-gas/sum/lsum, facets duoarea=NUS, process=ENG.
  • DUC/Rig source: https://www.eia.gov/outlooks/steo/xls/STEO_m.xlsx, Table 10a. 기존 DPR Excel 업데이트 중단을 반영한 대체 소스가 이미 코드에 적용되어 있었고, 이번에는 다운로드 실패 시 placeholder 결과를 반환하는 경로를 유지 확인.
  • Yahoo/FnGuide/DART/KRX/Naver 계열은 현재 sandbox DNS 제한 때문에 실제 데이터 성공 여부를 이 세션에서 확정하지 못함. 다만 dry-run 기준 대부분 예외 없이 종료됨.

수정 전후 메트릭

기준 백업: /Users/ron/.openclaw/cron/jobs.json.bak.oil-cron-fix-1776129204614 → 현재 /Users/ron/.openclaw/cron/jobs.json

항목 수정 전 수정 후
키워드 hit 크론 24 24
enabled 관련 크론 16 13
enabled인데 payload.command/payload.text가 남은 크론 13 0
enabled agentTurn인데 payload.message가 없는 크론 8 0
enabled oil main/systemEvent 중복 리마인더 3 0
enabled Telegram delivery인데 chatId/to 누락 0* 0
회귀 테스트 없음 6개 통과
eia-energy-3indicators dry-run exit 1 exit 0

* 첫 백업 시점에는 이미 일부 Telegram 메타 보강이 들어간 상태였음. 과거 run/error 로그에는 chatId/channel 관련 실패가 확인됨.

수동 실행 결과

결과 원본: /Users/ron/knowledge-agent/400-reports/260414_oil_cron_fix.manual_results.json

크론/스크립트 결과 확인 내용
oil-supply-monitor TIMEOUT(180s) 수동 harness 180초 제한에서 뉴스/웹 인텔리전스 단계 진행 중 timeout. Cron payload는 900초. sandbox 네트워크/GitHub token 경고가 남음.
upstream-tracker SUCCESS(exit 0) Yahoo/EIA DNS 실패로 데이터 0건이나 dry-run 종료 성공.
tanker-tracker SUCCESS(exit 0) Yahoo DNS 실패로 데이터 0건이나 dry-run 종료 성공.
collect-cluster semiconductor SUCCESS(exit 0) 외부 DNS 실패로 Tier1 0건이나 예외 없이 종료.
collect-cluster petrochemical SUCCESS(exit 0) 외부 DNS 실패로 Tier1 0건이나 예외 없이 종료.
petrochemical-report SUCCESS(exit 0) disabled 크론. dry-run/report 경로는 No data를 출력하고 종료.
energy-data-collector SUCCESS(exit 0) EIA DNS 실패를 WARN 처리하고 “수집된 지표 없음 — 종료”.
commodity-spike-morning SUCCESS(exit 0) dry-run/force 완료, alert log 저장 확인.
commodity-spike-watch SUCCESS(exit 0) dry-run 완료, 급변 없음. yfinance DNS/empty 실패는 비치명.
copper-market-collector SUCCESS(exit 0) dry-run 완료, 알림 대상 시그널 없음.
eia-energy-3indicators SUCCESS(exit 0) 수정 후 재실행. feedgas primary/fallback 모두 DNS 실패했지만 DUC/rig placeholder 2개 반환 후 종료 성공.
cu-fnguide-snapshot SUCCESS(exit 0) DNS/페이지 로드 실패 목록을 JSON으로 반환하고 종료.

실행한 검증 명령

cd /Users/ron/.openclaw/workspace && python3 -m py_compile \
  scripts/pipeline/copper_market_collector.py \
  scripts/pipeline/eia_energy_collector.py \
  scripts/pipeline/commodity_spike_analyzer.py \
  scripts/pipeline/tanker_tracker.py \
  tests/test_oil_energy_crons.py \
  tests/test_eia_energy_collector_resilience.py

결과: 성공

cd /Users/ron/.openclaw/workspace && python3 -m pytest \
  tests/test_oil_energy_crons.py \
  tests/test_eia_energy_collector_resilience.py -q

결과: 6 passed in 0.07s

cd /Users/ron/.openclaw/workspace && \
PYTHONPATH=/Users/ron/.openclaw/workspace/scripts \
python3 scripts/pipeline/eia_energy_collector.py --dry-run --weeks 4

결과: exit 0

엣지 케이스

  1. agentTurncommand/text만 있으면 OpenClaw worker가 실행 명령으로 보지 않고 LLM 대화로 처리할 수 있음.
  2. main/systemEvent 리마인더는 실제 스크립트를 실행하지 않고 “작업 생성/수정 질문”으로 재귀될 수 있음.
  3. Telegram channel=telegram 메타가 남아 있는데 chatId/to가 없으면 delivery 단계에서 실패 가능. 그래서 활성 관련 크론은 누락 0건으로 고정.
  4. send_dm(level="alert")는 현재 gateway에서 INFO 취급이지만, 정책 혼동을 막기 위해 루틴 크론은 level="info"로 통일.
  5. EIA primary API가 DNS/5xx/스키마 변경으로 예외를 내면 fallback을 시도해야 함. fallback도 실패하면 해당 지표만 누락/placeholder 처리.
  6. DUC/Rig STEO Excel이 다운로드 실패하면 값은 없지만 상태 객체(DOWNLOAD_FAILED)를 반환해야 전체 보고 파이프라인이 깨지지 않음.
  7. oil_supply_monitor.py는 웹/뉴스 단계가 길어 180초 수동 harness에서는 timeout 가능. cron payload는 900초라 운영 실행 여유는 더 큼.
  8. 외부 소스 전체 DNS 장애 시 “데이터 0건”과 “스크립트 실패”를 분리해야 함. 이번 검증은 대부분 데이터 0건이지만 exit 0으로 종료됨.
  9. disabled 관련 크론은 경로만 정리하고 enabled 상태는 유지하지 않음. 비활성 작업을 임의로 살리지 않음.
  10. shared/llm.py와 모델 체인/순서는 다른 세션 작업 범위라 수정하지 않음.

Remaining Risks

  • 현재 세션 sandbox 네트워크 제한 때문에 EIA/Yahoo/FnGuide/DART/KRX/Naver의 실제 운영 네트워크 성공은 완전 검증하지 못함.
  • oil-supply-monitor는 180초 수동 제한에서 완료 전 timeout. 900초 운영 제한에서 끝나는지는 다음 실제 크론 run log로 확인 필요.
  • GitHub OAuth token 경고가 웹/뉴스 보강 단계에 남음. 치명적 실패는 아니지만 데이터 품질 저하 가능.

자체 평가

  • 4.6/5
  • 미달 항목: 네트워크 허용 환경에서 oil-supply-monitor 전체 완료까지는 확인하지 못함.