Why: 매주 1회 무조건 큐레이션만 있는 현 구조를 다중 트리거+적응형
시그널 모니터링으로 확장. 좋은 수치(z≥1.5) 일 때만 텔레그램 보고.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UpdatePayload schema (task_id/status/progress/message/video_url/error).
404 if task not found. insta/music-lab과 동일 패턴 + video_url 필드.
Plan-B-Video Phase 1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NAS video-lab 신설. python:3.12-alpine 기반. redis>=5.0 의존성.
영상 외부 호출 없음(gateway만) — 외부 API 의존 없음.
Plan-B-Video Phase 1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
기존 13+1 외부 API 호출 함수는 web-ai/services/music-render/providers로 이식.
NAS는 SUNO_MODELS (정적 데이터)만 잔존. SUNO_API_KEY = "" sentinel.
Plan-B-Music Phase 3 (cutover 4/4).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code review found: empty dict `{}` was falsy and would silently skip
add_track. Use explicit None check.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SP-5 + SP-6 — 모든 Suno(13) + MusicGen(1) 외부 호출 + sync helpers(4)를
Windows music-render로 이전. NAS music-lab은 Redis push(async) +
httpx forward(sync)만. SUNO_API_KEY는 Windows .env 단독 보유 (spec §9).
17 task: NAS 수신부(1-2) → Windows worker(3-10) → NAS cutover(11-14) →
nginx 차단 + end-to-end 검증(15-17).
박재오 결정: 모든 Suno + MusicGen 일괄 이전 (Plan-B-Insta 패턴 + sync forward 추가).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
End-to-end 검증 중 발견된 2 가지 인프라 누락 보완:
1) frontend 컨테이너에 /data/insta_cards 마운트 추가 (NAS의 실저장 위치는
data/insta/insta_cards/<slate_id>/ 로 기존 insta-lab 컨테이너가 사용)
2) nginx /media/insta/ location → /data/insta_cards/ alias
이로써 Windows insta-render worker가 result_path "/media/insta/<id>/01.png"
로 보낸 URL이 NAS frontend nginx에서 정상 서빙됨.
Plan-B-Insta Phase 5 (검증) — T15 end-to-end 디버깅 fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Layer 1·2: IP 화이트리스트 (192.168.45.0/24 LAN + 100.64.0.0/10 Tailscale).
Layer 3: X-Internal-Key 헤더 (FastAPI dependency, 별도 검증).
외부에서 직접 호출 시 403 (nginx deny), LAN에서 키 없으면 401 (FastAPI).
Windows insta-render만 호출 가능.
Plan-B-Insta Phase 4.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NAS에서 더 이상 카드 렌더 안 함 → Windows insta-render 워커로 완전 이전.
- card_renderer.py를 1줄 deprecation stub로 교체
- main.py의 import card_renderer 제거 + startup/shutdown hook 정리
- requirements.txt에서 playwright 삭제
- Dockerfile에서 Chromium 30+ dep 라인 + playwright install 제거 → image ~50% 감소
- test_card_renderer.py 폐기 (Windows 측 test_worker.py가 대체)
- test_main.py의 create_slate 테스트를 Redis-push 플로우에 맞게 업데이트
Plan-B-Insta Phase 3 완료.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
박재오: NAS .env에 INTERNAL_API_KEY=$(openssl rand -hex 32) 추가 필요.
같은 값을 Windows insta-render .env에 보관 (대칭).
Plan-B-Insta Phase 1 완료.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Windows insta-render worker가 작업 진행률·완료·실패를 보고할 수신부.
X-Internal-Key 인증 필수. 4건의 단위 테스트로 status·error·result_path 검증.
Plan-B-Insta Phase 1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous push synced new deploy.sh to /runtime/scripts but the deploy
that came with that push had already started under the old script —
so redis (INFRA_SERVICES) was not brought up. This empty commit
forces the deployer to run the new script.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous deploy.sh only started services listed in BUILD_TARGETS, so the
newly-added redis service never came up after the SP-1 commit pushed to
NAS. Split image-based infra (redis) into INFRA_SERVICES and call
'docker compose up -d $INFRA_SERVICES' after the BUILD_TARGETS rebuild.
stop/rm is intentionally skipped for INFRA_SERVICES so AOF data
(/runtime/redis-data) survives each deploy cycle. Future infra services
(prometheus, grafana, ...) can join the same list.
Also add redis to HEALTH_ENDPOINTS so deployer's docker-inspect health
check waits for redis to report healthy before declaring DEPLOY_OK.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
분산 아키텍처 base 인프라 셋업. 8 task:
- Task 1-2: NAS docker-compose redis 서비스 추가 + 검증
- Task 3-5: Windows AI WSL2 + Docker Engine + Tailscale 설치
- Task 6-7: NAS SMB 자격증명·마운트 (/etc/fstab 자동화)
- Task 8: 통합 검증 (redis PING, /mnt/nas 양방향 R/W, docker hello-world)
SP-2 작업은 박재오 Windows AI 머신 192.168.45.59에서 직접 실행 필요.
Claude는 SP-1만 직접 처리, SP-2는 명령어·검증 가이드 제공.
후속 Plan-B-Insta/Music/Video/Infra의 prerequisite.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
다음 커밋에서 /api/webai/portfolio·news-sentiment·screener/run에
in-memory TTLCache 적용 예정.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
web-ai stock_client TTL 증가 (60/300/60 → 180/600/300) + NAS stock
TTLCache 도입 (cachetools, webai_cache 모듈, 3 endpoint 적용).
2-layer cache로 V2 재시작 시점부터 NAS 인바운드 호출 70% 감소 예상.
8개 task, TDD 적용 (회귀 테스트 3건 + cache 단위 테스트 6건).
~40분 작업.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
박재오 7결정 + Obsidian 3개 문서(7결정 통합/API 부하/역할 분담)를
실행 가능한 형태로 정리.
12개 SP 분할 (Track A Quick Win 2건 + Track B Infrastructure 10건),
의존성 그래프, 시간대 조건부 우선순위(평일 비휴장일만 트레이딩 HIGH),
Windows Render Worker 통합 패턴 (인스타·음악·영상 셋이 같은 구조),
Redis 큐 컨벤션, SMB direct write + NAS internal webhook,
X-WebAI-Key / X-Internal-Key 분리, 3-layer 차단(IP 화이트리스트 +
Tailscale + 헤더), Suno+영상 API 키 Windows 이전 명세.
첫 plan 대상: Track A (SP-A1 web-ai 캐시 TTL + SP-A2 NAS stock
TTLCache, ~40분 작업, V2 재시작 시 NAS 인바운드 70% 감소).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#10 NAS LLM 호출 → Windows AI 통일 — 확인 결과 이미 적용. NAS .env가
LLM_PROVIDER=claude + OLLAMA_URL=192.168.45.59:11435. NAS Celeron에서
LLM 추론 안 함. 코드 변경 불필요.
#11 컨테이너 리소스 제한 (cpus 0.5 등) — 박재오 진행 금지. J4025 2C
환경에서 오히려 throughput 손해라는 판단.
#12 NAS 하드웨어 업그레이드 — 박재오 보류 결정.
또한 web-ai V1(:8000)+V2(:8001)+launcher 총 4개 process 종료. NAS API
polling 부담 즉각 감소.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#6 insta-lab Chromium Browser Pool — Playwright/Chromium 인스턴스를
모듈 레벨에서 보관하고 매 슬레이트마다 reuse. 카드 10장 렌더의
launch 비용 (~3초/회)이 사라짐. startup/shutdown lifecycle hook 추가.
crashed/disconnected 시 lazy 재초기화.
#8 realestate-lab 수집 병렬화 — collect_all과 delete_old_completed가
서로 다른 데이터 영역이라 ThreadPoolExecutor(2)로 병렬. asyncio.gather
대신 thread executor를 쓴 이유는 BackgroundScheduler+동기 함수 환경
에서 자연스럽고 추가 의존성 없기 때문. 매칭은 일관성 유지로 순차.
#7 stock async — 보류. 재진단 결과 stock은 BackgroundScheduler 사용
중이라 main loop 블로킹 없음. fetch 4회는 network I/O wait가
대부분이라 to_thread도 의미 없음. 진짜 효과를 보려면 AsyncIOScheduler
전환 + aiohttp 병렬이라 큰 리팩토링. 박재오 판단 대기.
CHECK_POINT.md 갱신.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
J4025 Celeron 2C/2.0GHz에서 oversaturation을 일으키던 5개 패턴 해소.
1) 09:00 cron 스태거링 — agent-office insta_trends 09:00 / lotto 09:05 /
youtube 09:10, realestate-lab collect 09:15. 동시 실행 4개가 직렬
분산되어 1분 단위로 분산됨.
2) lotto Monte Carlo 08:05 → 08:30 — stock 08:00 cron과 25분 분리.
3) insta-lab card_renderer.render_slate를 asyncio.Semaphore(1)로 감쌈.
동시 슬레이트 렌더 요청이 와도 Chromium 인스턴스 1개만 직렬 launch.
4) docker-compose healthcheck interval 30s → 60s (9 백엔드 + frontend
총 10개). 30초마다 동시 healthcheck로 인한 CPU 잡음 절반으로.
5) 9개 백엔드 Dockerfile CMD에 --workers 1 명시. 기본값 의존 제거.
CHECK_POINT.md 갱신 — 즉시 5건 체크 + 변경 이력 한 줄.
적용 효과 검증: NAS 재기동 후 `docker stats` 비교.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>