← 리포트 목록
analyst/pipeline NO_SEND dry-run 표준화
2026-04-24
no
[no-send, dry-run, analyst, telegram, hermes]
analyst sender NO_SEND/dry-run 모드 표준화
결론
6개 대상 모두 NO_SEND=1 / DRY_RUN=1 / ANALYST_COMMON_NO_SEND=1 / --dry-run / --no-send 계열을 표준 인식하도록 맞췄다.
| 대상 | 적용 결과 | NO_SEND=1 검증 | 일반 모드 검증 |
|---|---|---|---|
| macro | 표준 가드 적용 | sender 호출 0 | fake sender 1회 |
| fundamental | 표준 가드 적용 | sender 호출 0 | fake sender 1회 |
| technical | analyst_common_sender.py 표준화 |
sender 호출 0 | fake sender 1회 |
| pm | analyst_common_sender.py 표준화 |
sender 호출 0 | fake sender 1회 |
| market_indicator | main + dedup wrapper 가드 적용 | sender 호출 0 | fake sender text/photo 각각 1회 |
| oil_supply | main + dedup wrapper 가드 적용 | sender 호출 0 | fake sender text/photo 각각 1회 |
실제 외부 Telegram 발송은 하지 않았다. “일반 실행 → 정상 발송”은 fake sender monkeypatch로 정상 호출 경로가 살아있는지 검증했다.
변경 파일
공통 가드 추가:
/Users/ron/.hermes/workspace/scripts/shared/no_send_guard.py
/Users/ron/.hermes/workspace/shared/no_send_guard.py
적용 파일:
/Users/ron/.hermes/workspace/scripts/macro_redesign_report.py
/Users/ron/.hermes/workspace/scripts/fundamental_redesign_report.py
/Users/ron/.hermes/workspace/scripts/analyst_common_sender.py
/Users/ron/.hermes/workspace/scripts/pipeline/market_indicator_tracker.py
/Users/ron/.hermes/workspace/scripts/pipeline/oil_supply_monitor.py
백업:
*.bak-no-send-standard-20260424
공통 가드
shared/no_send_guard.py가 인식하는 값:
NO_SEND=1
DRY_RUN=1
ANALYST_COMMON_NO_SEND=1
--dry-run
--no-send
제공 함수:
env_truthy(name)
env_no_send()
flags_no_send(argv)
no_send_requested(argv=None, *extra)
dry_run_result(sector="market")
no_send_log_line(component, body_len=None)
패치 내용
macro
- 기존:
--no-send,ANALYST_COMMON_NO_SEND=1만 인식 - 변경:
NO_SEND=1,DRY_RUN=1,ANALYST_COMMON_NO_SEND=1,--dry-run,--no-send인식 - 발송 직전
dry_run_result()반환 - stderr에
macro_redesign: NO_SEND active — send skipped body_len=...기록
fundamental
- 기존 자체 가드가 있었으나 공통 가드로 표준화
NO_SEND=1실행 시tg.send_sector_result()미호출- stderr에
fundamental_redesign: NO_SEND active — send skipped body_len=...기록
technical / pm
- 두 analyst는
analyst_common_sender.py를 통해 발송 - 기존:
ANALYST_COMMON_NO_SEND=1만 인식 - 변경:
NO_SEND=1,DRY_RUN=1,ANALYST_COMMON_NO_SEND=1,--dry-run,--no-send인식 - CLI 사용법도
[--dry-run|--no-send] <analyst> <latest.json> <tsv> <wrapper.log>로 확장
market_indicator
NO_SEND=1이면 수집 후 저장/발송 없이 dry-run 결과로 반환_dedup_send_sector,_dedup_send_sector_photo,_dedup_send_photo,_dedup_send_sector_album,_dedup_send_notification_center_chunked에도 NO_SEND 가드 삽입- 즉 main 레벨과 발송 wrapper 레벨 이중 차단
oil_supply
NO_SEND=1이면 리포트/차트 생성 후 Telegram 발송 블록 스킵_dedup_send_sector,_dedup_send_photo,_dedup_send_sector_photo,_dedup_send_sector_album,_dedup_send_notification_center_chunked에도 NO_SEND 가드 삽입
검증 1 — 4개 analyst NO_SEND=1 실제 실행
실행:
NO_SEND=1 python3 macro_redesign_report.py ...
NO_SEND=1 python3 fundamental_redesign_report.py ...
NO_SEND=1 python3 analyst_common_sender.py technical ...
NO_SEND=1 python3 analyst_common_sender.py pm ...
notification_center_log 변화:
notification_log_before=223 after=223 delta=0
출력:
macro: status=dry_run, message_id=null, no_send=true, body_len=2183
fundamental: message_id=null, body_len=2291, blacklist_hits=[]
technical: status=dry_run, message_id=null, no_send=true, body_len=2484
pm: status=dry_run, message_id=null, no_send=true, body_len=2455
stderr:
macro_redesign: NO_SEND active — send skipped body_len=2183
fundamental_redesign: NO_SEND active — send skipped body_len=2291
analyst_common_sender:technical: NO_SEND active — send skipped body_len=2484
analyst_common_sender:pm: NO_SEND active — send skipped body_len=2455
검증 2 — market/oil NO_SEND=1 sender-level 실행
외부 발송 없이 fake sender로 계측했다.
[
{
"module": "market",
"no_send_results": [true, true, true],
"no_send_underlying": {"sector": 0, "photo": 0, "sector_photo": 0, "nc": 0},
"normal_results": [true, true, true],
"normal_underlying_total": {"sector": 1, "photo": 1, "sector_photo": 1, "nc": 0}
},
{
"module": "oil",
"no_send_results": [true, true, true],
"no_send_underlying": {"sector": 0, "photo": 0, "sector_photo": 0, "nc": 0},
"normal_results": [true, true, true],
"normal_underlying_total": {"sector": 1, "photo": 1, "sector_photo": 1, "nc": 0}
}
]
판정:
NO_SEND=1에서는 text/photo/sector_photo 발송 함수가 실제 sender를 호출하지 않음- 일반 모드에서는 동일 경로가 fake sender를 호출함
- 따라서 차단은 작동하고, 정상 발송 경로도 깨지지 않음
검증 3 — py_compile
python3 -m py_compile \
macro_redesign_report.py \
fundamental_redesign_report.py \
analyst_common_sender.py \
pipeline/market_indicator_tracker.py \
pipeline/oil_supply_monitor.py \
shared/no_send_guard.py
OK
CLAUDE.md 운영 규칙 추가 권고
실제 파일은 수정하지 않고 권고로 남긴다.
강제 재실행/수동 재검증은 기본적으로 NO_SEND=1 ANALYST_COMMON_PRINT_BODY=1로 먼저 실행한다. 실제 발송은 렌더링·길이·HTML·중복 체크 통과 후에만 수행한다.
남은 리스크
- market/oil은 전체 main을 네트워크 수집까지 돌리는 방식 대신 sender-level로 검증했다. 이유는 실제 외부 발송/수집 부하와 노이즈를 피하기 위해서다.
- 이번 범위는 요청된 6개에 한정했다. 다른 pipeline도 이미 dedup은 적용됐지만 NO_SEND 표준화까지 모두 적용된 것은 아니다.
자체평가
| 기준 | 점수 | 근거 |
|---|---|---|
| 정확성 | 4.4/5 | 6개 대상 모두 공통 env/flag 인식 및 sender 미호출 검증 |
| 완성도 | 4.3/5 | 공통 가드 추가, analyst/main/wrapper 경로 반영 |
| 검증 | 4.3/5 | 4 analyst 실제 NO_SEND 실행, market/oil fake sender 계측, py_compile 통과 |
| 최소 변경 | 4.4/5 | 발송 직전 가드와 공통 유틸만 추가, 실제 발송 로직 구조는 유지 |
종합: 4.35/5
DONE