석유 공급망 크론 정상화 최종 보고
결론
~/.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, seriesN9133US2. - Feedgas fallback:
shared.eia_client.get_ng_feedgas_demand(), routenatural-gas/sum/lsum, facetsduoarea=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
엣지 케이스
agentTurn에command/text만 있으면 OpenClaw worker가 실행 명령으로 보지 않고 LLM 대화로 처리할 수 있음.- main/systemEvent 리마인더는 실제 스크립트를 실행하지 않고 “작업 생성/수정 질문”으로 재귀될 수 있음.
- Telegram
channel=telegram메타가 남아 있는데chatId/to가 없으면 delivery 단계에서 실패 가능. 그래서 활성 관련 크론은 누락 0건으로 고정. send_dm(level="alert")는 현재 gateway에서 INFO 취급이지만, 정책 혼동을 막기 위해 루틴 크론은level="info"로 통일.- EIA primary API가 DNS/5xx/스키마 변경으로 예외를 내면 fallback을 시도해야 함. fallback도 실패하면 해당 지표만 누락/placeholder 처리.
- DUC/Rig STEO Excel이 다운로드 실패하면 값은 없지만 상태 객체(
DOWNLOAD_FAILED)를 반환해야 전체 보고 파이프라인이 깨지지 않음. oil_supply_monitor.py는 웹/뉴스 단계가 길어 180초 수동 harness에서는 timeout 가능. cron payload는 900초라 운영 실행 여유는 더 큼.- 외부 소스 전체 DNS 장애 시 “데이터 0건”과 “스크립트 실패”를 분리해야 함. 이번 검증은 대부분 데이터 0건이지만 exit 0으로 종료됨.
- disabled 관련 크론은 경로만 정리하고 enabled 상태는 유지하지 않음. 비활성 작업을 임의로 살리지 않음.
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전체 완료까지는 확인하지 못함.