# task-596.1 완료 보고서: AI집단지성 대화 메모리 지능화 (Phase 1/2)

**S**: AI집단지성 그룹챗(잼민이/코덱스/클로디)의 대화가 인메모리 deque(20개)에만 저장되어, 봇 재시작 시 모든 대화가 소멸되고 장기 맥락 유지가 불가능하다.

**C**: 봇 재시작이 발생할 때마다 대화 맥락이 완전히 초기화되며, 봇들이 과거 논의 맥락 없이 매번 처음부터 대화하는 문제가 있다. 대화 요약/정리 기능도 부재.

**Q**: JSONL 영속화 + 자동 요약 + /정리 명령어를 도입하여 봇 재시작 후에도 대화 맥락을 유지하고, 봇 응답 품질을 개선할 수 있는가?

**A**: JSONL 파일 영속화(fcntl.flock 잠금), 50개 메시지 자동 요약(call_claude), format_context 요약 통합, /정리 명령어(insight 생성)를 구현했다. 인메모리 버퍼를 20→50으로 확대하고, lazy load로 봇 시작 시 자동 복원. pytest 50개 전체 통과, pyright 0 에러.

---

## 수행 내역

### 1-1. 대화 영속화
- JSONL 파일 저장: `memory/groupchat/YYYY-MM-DD.jsonl`
- `fcntl.flock()` 파일 잠금으로 동시 쓰기 방지
- 파일 저장 실패 시 인메모리만 동작 (graceful degradation)
- 인메모리 버퍼 20 → 50개 확대

### 1-2. 자동 요약 생성
- 50개 메시지마다 `_generate_summary()` 자동 트리거
- `call_claude()` (Sonnet)로 핵심 논점 3~5줄 요약
- 요약 파일: `memory/groupchat/summaries/YYYY-MM-DD_NNN.json`
- `asyncio.create_task`로 비동기 실행 (메인 플로우 비블로킹)
- 실패 시 로깅 후 다음 트리거 대기

### 1-3. 봇 컨텍스트 강화
- `format_context()` 확장: 요약 있을 때 `[이전 대화 요약]` + `[최근 대화]` 섹션 자동 포함
- `get_recent_summaries(limit=3)`: 오늘 요약 파일 최근 N개 로드
- 요약 없을 때는 기존 `[이전 대화]` 포맷 유지 (하위호환)

### 2-1. /정리 명령어
- `generate_insight(chat_id)` async 메서드: 핵심 논점/결론/액션아이템 요약
- 결과 저장: `memory/groupchat/insights/YYYY-MM-DD_insight_NNN.md`
- `main_bot.py`에 `/정리` CommandHandler 등록 (클로디 봇 담당)

### Lazy Load (추가 구현)
- `_loaded_chats: set[int]`로 이미 로드한 chat_id 추적
- `add_message()` 호출 시 첫 메시지에 대해 `load_today()` 자동 실행
- 명시적 startup load 없이도 안전하게 대화 복원

---

## 생성/수정 파일

- `/home/jay/workspace/services/multimodel-bot/conversation_memory.py` — 영속화, 요약, insight, lazy load 구현 (전면 재구현)
- `/home/jay/workspace/services/multimodel-bot/main_bot.py` — storage_base 명시, /정리 핸들러 추가
- `/home/jay/workspace/services/multimodel-bot/tests/test_conversation_memory.py` — 30개 테스트 추가 (총 50개)

---

## 테스트 결과

- **pytest**: 50 passed in 0.36s (기존 20 + 신규 30)
- **pyright**: conversation_memory.py 0 errors, main_bot.py 0 errors (로컬 pyrightconfig.json 사용)
- **포매팅**: black + isort 적용 완료

### 테스트 커버리지 분포
- TestPersistence: 5개 (JSONL 파일 생성/append/포맷/격리 검증)
- TestLoadToday: 5개 (파일 복원, 없는 파일, chat_id 필터링, 50개 제한, 필드 복원)
- TestSummaryGeneration: 7개 (카운트 추적, 50개 트리거, call_claude 호출, JSON 저장, 구조 검증, 실패 처리, 카운터)
- TestFormatContextWithSummaries: 6개 (요약 섹션, 없을 때, 최근 대화, get_recent_summaries)
- TestGenerateInsight: 4개 (반환값, md 저장, 파일명, 프롬프트)
- TestGracefulDegradation: 3개 (파일 실패, 인메모리 유지, 손상 라인 skip)

---

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **storage_base 기본값 변경** — lazy load 도입으로 `DEFAULT_STORAGE_BASE` → `None` 변경. main_bot.py에서 명시적 경로 전달.
   - conversation_memory.py:82, main_bot.py:29
2. **기존 TestDefaultMaxMessages 테스트 업데이트** — 기본 max_messages가 20→50으로 변경되면서 기존 테스트의 기대값도 50으로 업데이트.
   - tests/test_conversation_memory.py:225-237
3. **_schedule_summary의 동기/비동기 호환** — 테스트 환경(동기)과 운영 환경(비동기) 모두 대응하도록 `asyncio.iscoroutine()` 체크 + `get_running_loop()` RuntimeError 핸들링.
   - conversation_memory.py:231-239

---

## 다음 Phase

- **다음 Phase 지시서**: `/home/jay/workspace/memory/tasks/task-596.2.md`
- 내용: 30분 무활동 자동 요약, key_topics 추출, /정리 결과 아누 DM 전송, 아누 참조 연결고리
