fed3526b20
설정·스크립트·스킬·문서·큐레이션 메모리 추적. 시크릿(credentials/identity)·런타임 상태(state/logs/sessions/sqlite)· 백업(clobbered/bak)·dream 캐시는 .gitignore로 제외. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7.1 KiB
7.1 KiB
name, description, type
| name | description | type |
|---|---|---|
| 2026-04-27 감시종목 웹 뷰 신규 + 종목분석 메일 등락 표기 수정 | 비하이브 종목분석 메일의 현재가 등락 표기를 매입가 대비로 정정. 감시종목 실시간 웹 뷰(`https://stock.hyowons.net/`)와 launchd 서비스 신규. | project |
1. 종목분석 메일 등락 표기 버그 수정
증상
관리자님이 받으시는 비하이브 종목분석 메일·텔레그램의 "현재가" 줄에 붙는 등락이 전부 +0원, +0.00%으로 잘못 표기됨.
원인
behive_youtube_digest.py:fetch_current_price가 키움 ka10001의 change/change_pct 필드(전일대비)를 그대로 출력. 관리자님 의도는 매입가(entry['buy']['primary']) 대비 등락이었음.
수정
fetch_current_price(stock, buy_price=None)시그니처로 변경. buy_price 주어지면(price - buy_primary, pct)계산해서± N원, ± N% vs 매입가표기. 없으면 가격만 표시._buy_primary(entry)헬퍼로{primary, raw, levels}dict에서 numeric primary 안전 추출.- 이메일 경로(
format_entry_block) + 텔레그램 경로(format_telegram_block) 둘 다 매입가 전달하도록 수정.
검증: 워치리스트 7종목 전부 매입가 대비 정상 표기 확인 (예: 미래반도체 21,750원 (+2,750원, +14.47% vs 매입가)).
2. 감시종목 실시간 웹 뷰 신규
동기
관리자님이 매번 레이한테 "워치리스트 어떻게 됐어?" 물어보기 번거로워서 웹페이지로 보고 싶다 요청. 외부망에서도 폰으로 접근 가능해야 함.
결정 (대화 누적)
| 검토 사항 | 최종 결정 | 이유 |
|---|---|---|
| 정적 cron 푸시 vs 실시간 서버 | 실시간 Mac 서버 | 페이지 안 볼 땐 호출 0건이라는 관리자님 logic이 cron 모델과 안 맞음 |
| 자격증명 위치 | Mac에만 유지 | 키움 자격증명을 NAS로 옮기지 않음. 워크스페이스 분리 원칙 |
| 인증 | 없음 | read-only 페이지, 잔고 노출 없음(워치리스트만), 거래 권한 0. 위생 차원 noindex,nofollow + Referrer-Policy: no-referrer만 적용 |
| URL 형태 | 서브도메인 stock.hyowons.net |
폰 PWA 추가 시 깔끔, path 파싱 부담 0 |
| 외부 노출 경로 | NAS reverse proxy 경유 | NAS가 외부 노출(DDNS) 갖고 있어서 활용. Mac은 LAN/Tailscale 인터페이스만 응답 |
구현
scripts/behive_web.py(신규) — Python stdlibhttp.server.GET /한 라우트. watchlist 읽고 키움 ka10001 병렬 호출(8 thread) → 카드형 HTML 반환. JS 0, 인라인 CSS만. 새로고침 버튼은<a href="/">↻</a>(anchor — 페이지 GET이 곧 키움 새 호출).~/Library/LaunchAgents/ai.openclaw.stock.behive-web.plist(신규) —KeepAlive=true,ThrottleInterval=10, 부팅 자동 기동.- 모바일 UI: sticky 헤더, safe-area 처리, 40×40 터치 타겟, 720px 이하 1열 레이아웃, PWA 메타(
apple-mobile-web-app-*,theme-color).
외부 노출 인프라
폰/PC → https://stock.hyowons.net/ (Cafe24 도메인)
→ CNAME → stock.hyowons.duckdns.org (사용자 NAS DDNS)
→ 공인 IP 112.147.127.79 (NAS WAN)
→ Synology DSM reverse proxy
→ http://192.168.219.142:18790 (Mac mini LAN IP)
→ behive_web.py
- 인증서: Synology Let's Encrypt —
web.hyowons.net인증서에 SAN으로stock.hyowons.net포함 (관리자님 발급 완료). - Mac 서버 바인딩:
0.0.0.0:18790(모든 인터페이스). 외부망 직접 도달은 공유기 NAT 차단으로 보호. - macOS 방화벽: Application Firewall ON 상태에서 Python inbound 허용.
트러블슈팅 기록 (재발 방지용)
NAS → Mac 도달 실패 케이스를 겪었다. 진단 순서:
- macOS Application Firewall — Python 허용됐는지 (
socketfilterfw --getappblocked /usr/bin/python3). - Tailscale ShieldsUp —
tailscale debug prefs | grep ShieldsUp가 false인지. - NAS 호스트 OS의 Tailscale 라우트 — Synology Tailscale 패키지가 컨테이너로 돌면 host shell에
100.64.0.0/10라우트가 안 잡혀서 NAS의 일반 프로세스(reverse proxy nginx 포함)가 Tailscale IP로 outbound 못 함. - 우회 방법(현재 채택): LAN IP 직접 사용 —
192.168.219.142:18790으로 reverse proxy 대상 지정. 같은 LAN 세그먼트라 라우팅 문제 0.
LAN IP 안정화는 공유기 DHCP 예약(192.168.219.142 고정).
3. 문서·메모리 갱신
- 루트
CLAUDE.md— stock skills/scripts 섹션에behive_web.py추가 agents/stock/workspace/MEMORY.md— launchd 표에ai.openclaw.stock.behive-web등록 (상시 실행)
4. 운영 노트
- "감시종목 페이지 어디서 봐?" 질문에는 →
https://stock.hyowons.net/ - 새로고침 = 키움 ka10001 호출 — 가만히 보고 있으면 키움 호출 0건, 새로고침 누르면 그 시점 가격으로 갱신.
- 종목 추가 흐름은 변경 없음 — 비하이브 신규 영상 자동 감지 또는 수동
behive_youtube_digest.py add. watchlist.json 변경되면 다음 페이지 GET부터 자동 반영. - 카드 색상: 매입가 대비 +면 녹색 좌측 라인, -면 빨간색, 매입가 미설정 또는 0이면 회색.
- "조회 불가" 카드: 키움 API 실패 시 그 종목만 fallback 표기, 나머지는 정상 렌더 (페이지 전체가 죽지 않음).
4-2. 감시 삭제 기능 (2단계) 추가
데이터 모델
워치리스트 entry에 status·pending_delete_at 필드 도입:
- 없음 또는
"active"= 정상 감시중 "pending_delete"= 삭제예정 (UI에서 "삭제예정" 섹션, opacity 0.5로 흐리게)
웹 라우트 (behive_web.py)
POST /delete— status=pending_delete + pending_delete_at 기록POST /restore— status/pending_at 제거 (active 복귀)POST /purge— entry 완전 삭제 (onsubmit="return confirm()"한 번 더 확인)- 모두 form-urlencoded
stock=<종목명>받고 303 →/redirect - 인증 없음 — 외부 접근 시 NAS reverse proxy + URL 비밀성에 의존, 2단계 자체가 안전망
충돌 방지 가드
| 위치 | 변경 | 이유 |
|---|---|---|
behive_youtube_digest.py:cmd_save |
기존 entry가 pending_delete면 mark_seen만 하고 덮어쓰기 skip |
비하이브 재분석으로 사용자 의도 무력화 방지 |
watchlist_monitor.py:run |
pending_delete entry는 continue로 스킵 |
삭제예정 종목에 buy/target/stop 알림 안 가도록 |
자동 삭제 트리거는 원래 없었음 (모니터·save 둘 다 read 또는 add only). 따라서 자동/수동 충돌은 위 두 가드만으로 해결됨.
UI 동작
- active 종목 자세히 보기 → "감시 삭제" 버튼 → pending_delete로 이동 (페이지 하단 "삭제예정" 섹션에 흐리게)
- pending_delete 종목 자세히 보기 → "복원" / "완전 삭제" 두 버튼. 완전 삭제는 confirm 다이얼로그 한 번 더.
매매 절대 원칙
- 이번 작업은 read-only 조회 인프라 + 워치리스트 메타 관리(삭제). 매수·매도 함수 추가 없음. 웹 페이지에 거래 액션 버튼 절대 추가 금지 (조회 전용 원칙).