feat: add playbook persistence with DB schema and CRUD store (issue #82) #107

Merged
jihoson merged 1 commits from feature/issue-82-playbook-persistence into main 2026-02-08 21:07:13 +09:00
Collaborator

Summary

  • src/db.py: playbooks 테이블 추가 — UNIQUE(date, market) 제약, 인덱스
  • src/strategy/playbook_store.py: PlaybookStore CRUD 클래스
    • save() / load(): DayPlaybook JSON 직렬화/역직렬화 (Pydantic)
    • get_status() / update_status(): 상태 관리 (pending/ready/failed/expired)
    • increment_match_count(): 장중 시나리오 매칭 횟수 추적
    • get_stats(): 전체 JSON 없이 요약 정보 조회
    • list_recent(): 최근 플레이북 목록 (시장별 필터)
    • delete(): 삭제
  • 23 tests, playbook_store.py 100% coverage
  • 전체 442 tests passed

Test plan

  • TestSchema: 테이블 존재, UNIQUE 제약 (INSERT OR REPLACE)
  • TestSaveLoad: 저장/로드, 필드 보존, 시장별/날짜별 분리, 교체
  • TestStatus: 상태 조회/변경, not found
  • TestMatchCount: 증분, not found
  • TestStats: 요약 조회, not found
  • TestListRecent: 최신순 정렬, 시장 필터, 빈 결과
  • TestDelete: 삭제, not found, 타 시장 유지

Closes #82

## Summary - `src/db.py`: playbooks 테이블 추가 — `UNIQUE(date, market)` 제약, 인덱스 - `src/strategy/playbook_store.py`: PlaybookStore CRUD 클래스 - `save()` / `load()`: DayPlaybook JSON 직렬화/역직렬화 (Pydantic) - `get_status()` / `update_status()`: 상태 관리 (pending/ready/failed/expired) - `increment_match_count()`: 장중 시나리오 매칭 횟수 추적 - `get_stats()`: 전체 JSON 없이 요약 정보 조회 - `list_recent()`: 최근 플레이북 목록 (시장별 필터) - `delete()`: 삭제 - 23 tests, playbook_store.py 100% coverage - 전체 442 tests passed ## Test plan - [x] TestSchema: 테이블 존재, UNIQUE 제약 (INSERT OR REPLACE) - [x] TestSaveLoad: 저장/로드, 필드 보존, 시장별/날짜별 분리, 교체 - [x] TestStatus: 상태 조회/변경, not found - [x] TestMatchCount: 증분, not found - [x] TestStats: 요약 조회, not found - [x] TestListRecent: 최신순 정렬, 시장 필터, 빈 결과 - [x] TestDelete: 삭제, not found, 타 시장 유지 Closes #82
agentson added 1 commit 2026-02-08 21:00:34 +09:00
feat: add playbook persistence with DB schema and CRUD store (issue #82)
Some checks failed
CI / test (pull_request) Has been cancelled
7f2f96a819
- Add playbooks table to src/db.py with UNIQUE(date, market) constraint
- PlaybookStore: save/load/delete, status management, match_count tracking,
  list_recent with market filter, stats without full deserialization
- DayPlaybook JSON serialization via Pydantic model_dump_json/model_validate_json
- 23 tests, 100% coverage on playbook_store.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Collaborator

리뷰 응답

Finding 1: save()의 match_count/status 초기화

의도된 동작입니다. 설계 근거:

  • save()는 PreMarketPlanner가 장 전에 새 플레이북을 생성할 때만 호출
  • 재생성(retry 포함) = 새 플레이북이므로 match_count=0, status=READY로 리셋이 정확한 시맨틱
  • 장중 카운트/상태 업데이트는 increment_match_count(), update_status()가 별도로 담당
  • 장중에 save()를 호출하는 코드 경로는 존재하지 않음 (Issue 1-7 main.py 통합에서 보장 예정)

Finding 2: 기존 DB 부분 스키마 마이그레이션

현시점 불필요. playbooks 테이블은 V2에서 신규 도입되어 레거시 스키마가 존재하지 않습니다. trades 테이블처럼 기존 DB와의 호환이 필요한 경우가 아니므로, 향후 스키마 변경 시 마이그레이션 로직을 추가하겠습니다.

## 리뷰 응답 ### Finding 1: save()의 match_count/status 초기화 **의도된 동작입니다.** 설계 근거: - `save()`는 PreMarketPlanner가 장 전에 새 플레이북을 생성할 때만 호출 - 재생성(retry 포함) = 새 플레이북이므로 `match_count=0`, `status=READY`로 리셋이 정확한 시맨틱 - 장중 카운트/상태 업데이트는 `increment_match_count()`, `update_status()`가 별도로 담당 - 장중에 `save()`를 호출하는 코드 경로는 존재하지 않음 (Issue 1-7 main.py 통합에서 보장 예정) ### Finding 2: 기존 DB 부분 스키마 마이그레이션 **현시점 불필요.** `playbooks` 테이블은 V2에서 신규 도입되어 레거시 스키마가 존재하지 않습니다. `trades` 테이블처럼 기존 DB와의 호환이 필요한 경우가 아니므로, 향후 스키마 변경 시 마이그레이션 로직을 추가하겠습니다.
jihoson merged commit f20736fd2a into main 2026-02-08 21:07:13 +09:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jihoson/The-Ouroboros#107