#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>
The pixel-office game UI is gone, so simulating coffee-break /
nap / walk states no longer serves any purpose. Remove:
- scheduler's _check_idle_breaks job (no more 60s idle scan)
- BaseAgent.check_idle_break() and _break_until field
- 'break' from VALID_STATES and from transition() branches
- IDLE_BREAK_THRESHOLD / BREAK_DURATION_MIN / BREAK_DURATION_MAX
config knobs
- 'idle/break' guard in each agent's on_schedule (now just 'idle')
Agents now sit in 'idle' between scheduled jobs and explicit
commands. Display reads 'Idle' instead of churning between idle
and break.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
운영에서 사용자 디자인이 1122x1402로 작성됨. 1080x1350과 정확히 같은
4:5 종횡비지만 절대 사이즈만 다르므로 정확한 사이즈 강제는 과도.
- 검증: 종횡비 4:5 (±2% tolerance). 1080x1350·1122x1402 등 동일 비율
높은 해상도 모두 통과.
- Vision은 base64로 원본 분석 (사이즈 무관).
- Playwright는 background-size: cover로 1080x1350 컨테이너에 자동 fit.
- 비율이 깨지면 (예: 1024x1024 정사각) 여전히 reject.
test_validate_images_accepts_higher_resolution_4_5_ratio 신규 (1 case).
design_importer.py가 1080x1350 이미지 검증을 위해 `from PIL import Image`
사용. 운영 컨테이너에서 ModuleNotFoundError: No module named 'PIL' 발생.
card_renderer는 Playwright만 쓰므로 기존 requirements에 PIL이 없었음.
local pytest는 dev 환경에 Pillow가 이미 설치돼 있어 PASS — 운영 검증
구멍.
Pillow>=10 추가 → 다음 webhook 빌드 시 pip 설치.
사용자 디자인 PNG에 placeholder 텍스트가 이미 박혀있는 경우 대응.
Vision system prompt에 두 layer 요구:
(a) 마스킹 박스: placeholder 영역 좌표 + 주변 배경색으로 덮음
(b) 동적 텍스트 layer: 동일 좌표에 새 카피, 원본 폰트 스타일 모방
+ overflow:hidden으로 긴 카피가 박스 밖 새지 않게.
spec 4-3 + plan Task 3 step 3 동시 패치.
사용자가 만든 카드 디자인 이미지 10장을 Claude Sonnet Vision으로 분석해
페이지별 텍스트 영역·색·레이아웃 모방한 단일 card.html.j2 자동 생성.
핵심 결정:
- CLI 진입점 (MVP) — API endpoint는 후속
- env INSTA_DEFAULT_THEME 단일 theme — 슬레이트별 선택은 후속
- 파일명 자동 매핑 (cover→1, cta→10, 나머지 알파벳) + _order.json override
- card_renderer 폴백 가드 (theme HTML 없으면 default로)
- stock/app/test_scraper.py 삭제 — 미존재 함수 fetch_overseas_news를
import하는 untracked 임시 스크립트. 보존 가치 없음 (F8).
- blog-lab/ 디렉토리 잔재 (__pycache__만 남음) 완전 제거. 서비스는
feat/insta-agent 머지에서 이미 폐기됨.
- .gitignore에 .superpowers/ (스킬 캐시·세션 메타)와 CODE_REVIEW.md
(임시 리뷰 노트) 추가 — git status 노이즈 차단.
운영 .env에 ADMIN_API_KEY가 누락되면 verify_admin이 무조건 통과해서
/api/trade/balance, /api/trade/order 인증이 무력화되던 문제 차단.
- ADMIN_API_KEY 설정 + 올바른 키 → 통과 (기존 동작)
- ADMIN_API_KEY 설정 + 잘못된 키 → 401 (기존 동작)
- ADMIN_API_KEY 미설정 + ALLOW_UNAUTHENTICATED_ADMIN=true → 통과 (dev mode)
- ADMIN_API_KEY 미설정 + dev flag 없음 → 503 (신규, 운영 보호)
.env.example에 신규 ALLOW_UNAUTHENTICATED_ADMIN=false 안내 추가.
stock/pytest.ini 신규 (pythonpath=. 설정으로 tests 모듈 import 가능).
test_admin_auth.py 4 케이스 (RED → GREEN 검증, regression 포함).
str(abs_path).startswith(str(PACK_HOST_DIR))는 trailing slash가 없어
sibling 경로(/foo/packs ↔ /foo/packs_evil)를 통과시켜 DSM API에 잘못된
호스트 경로를 전달할 수 있었음. Path.relative_to 기반으로 컴포넌트 단위
엄격 검증으로 교체. test_sign_link_rejects_sibling_path 회귀 테스트
추가 (RED → GREEN 검증).
Google이 비공식 trends endpoint 두 가지(/trends/.../rss + /trends/api/dailytrends)
모두 404로 폐기 (NAS에서 직접 호출 시 확정). 대안으로 YouTube Data API v3
mostPopular(regionCode=KR, 50개)로 source 교체:
- source 이름: google_trends → youtube_trending
- 키워드: 영상 제목 정제 (대괄호·이모지 제거, 60자 limit)
- API 키: YOUTUBE_DATA_API_KEY (agent-office와 공유, .env 그대로 활용)
- 키 미설정 시 graceful skip
- docker-compose insta-lab에 환경변수 추가
- 테스트 9/9 pass (기존 6 + youtube 3 신규)
기존 curl http://lotto:8000/health은 deployer 컨테이너 내부에서만
Docker DNS가 'lotto'를 해석. 호스트 셸에서 sudo bash로 직접 실행 시
DNS 해석 실패해 모든 서비스가 HEALTH_FAIL로 오판정. docker inspect로
이미 정의된 compose healthcheck 결과를 직접 조회하도록 변경. starting
상태는 최대 60초 대기 후 최종 판정.