# task-612.1 완료 보고서: Codex 봇 개선 2건

## SCQA

**S**: multimodel-bot 서비스는 3개 AI 봇(잼민이/코덱스/클로디)이 Telegram 그룹챗에서 라운드 로빈 토론을 수행하는 시스템으로, 일일 활성 운영 중이다.

**C**: 두 가지 문제가 발생했다. (1) Codex CLI 에러 시 `stderr_text[-300:]`을 그대로 반환하여 시스템 프롬프트(페르소나 지시문)가 사용자에게 노출되는 보안 문제. (2) 토론 중 유저가 메시지를 보내면 `trigger_next_bot_response` 체인이 중복 시작되어 봇 응답 순서가 뒤섞이는 레이스 컨디션.

**Q**: stderr 노출을 차단하고, 동시 응답을 방지하여 안정적인 라운드 로빈 토론을 보장할 수 있는가?

**A**: (1) `_filter_error_lines()` 헬퍼로 stderr에서 "error" 포함 줄만 필터링하고, usage limit/auth 에러는 사전 정의 메시지로 대체. call_claude도 동일 로직 적용. (2) `asyncio.Lock` + `chain_running` 플래그 도입으로 체인 동시 실행 방지. 전체 264개 테스트 통과, pyright 에러 0건.

---

## 수정 파일 목록

### 항목 1: stderr 노출 방지

- `/home/jay/workspace/services/multimodel-bot/engine.py`
  - `import re` 추가
  - `_filter_error_lines()` 헬퍼 함수 신규 (145~152행)
  - `call_codex()`: auth 에러에서 `stderr_text[-300:]` 제거, usage limit 감지 추가, 기타 에러 error 줄 필터링 (188~197행)
  - `call_claude()`: returncode != 0이고 stdout 비어있을 때 stderr error 줄 필터링 반환 (244~250행)
- `/home/jay/workspace/services/multimodel-bot/tests/test_engine.py`
  - 신규 테스트 10개 추가 (TestCallCodex 7개, TestCallClaude 3개)

### 항목 2: 토론 순차 보장

- `/home/jay/workspace/services/multimodel-bot/discussion_manager.py`
  - `_chain_running` 딕셔너리 추가 (168행)
  - `is_chain_running()`, `set_chain_running()` 메서드 추가 (190~196행)
  - `stop_discussion()`에 chain_running 리셋 추가
  - `on_user_message()` 반환 타입 `None` → `bool` (새 토론: True, 기존 토론 중: False)
- `/home/jay/workspace/services/multimodel-bot/main_bot.py`
  - `_turn_lock = asyncio.Lock()` 모듈 수준 변수 추가 (30행)
  - `trigger_next_bot_response` 전체를 `async with _turn_lock:` 로 감싸기 (124행)
  - 체인 종료/에러 시 `set_chain_running(False)` 호출 (129, 134, 180, 191행)
- `/home/jay/workspace/services/multimodel-bot/codex_bot.py` — `is_chain_running` 가드 + `set_chain_running(True)` 추가 (94, 99행)
- `/home/jay/workspace/services/multimodel-bot/claude_bot.py` — 동일 패턴 적용
- `/home/jay/workspace/services/multimodel-bot/gemini_bot.py` — 동일 패턴 적용
- `/home/jay/workspace/services/multimodel-bot/tests/test_discussion_manager.py`
  - `TestDiscussionManagerChainGuard` 클래스 6개 테스트 추가

---

## 테스트 결과

- pytest: **264 passed, 0 failed** (0.96초)
  - 기존 248개 전체 회귀 없음
  - 신규 16개 (engine 10 + discussion_manager 6) 전체 통과
- pyright: engine.py, discussion_manager.py — **0 errors, 0 warnings**

---

## 발견 이슈 및 해결

### 자체 해결 (3건)

1. **auth 에러에서도 stderr 노출** — `stderr_text[-300:]` 사용하던 auth 에러 메시지에서도 시스템 프롬프트 노출 가능. 고정 메시지로 대체.
   - 수정: engine.py:191 — `(상세: {stderr_text[-300:]})` 제거
2. **call_claude에 에러 처리 부재** — returncode != 0이고 stdout 비어있을 때 빈 응답 fallback만 반환하여 에러 원인 불명. stderr error 줄 필터링 로직 추가.
   - 수정: engine.py:246~250
3. **개별 봇 handle_message에서 중복 체인 시작 가능** — 토론 중 유저 메시지 시 개별 봇이 `on_bot_response` + `create_task(trigger_fn)` 을 호출하여 기존 체인과 병행 실행. `is_chain_running` 가드 추가로 차단.
   - 수정: codex_bot.py:94, claude_bot.py:동일, gemini_bot.py:동일

---

## 설계 결정

- **`create_task` vs `await` 트레이드오프**: `create_task`를 유지하되 `asyncio.Lock`으로 직렬화. `await`로 변경 시 Telegram 메시지 전송 중 이벤트 루프가 블로킹되어 다른 핸들러 처리 지연 우려.
- **`chain_running` 플래그를 `DiscussionManager`에 배치**: 순환 임포트 방지 (개별 봇 → main_bot 임포트 불필요).
- **`on_user_message` bool 반환**: 기존 코드 호환성 유지 (반환값 무시 가능).

---

## QC 자동 검증

- **overall**: WARN (Gate PASS)
- file_check: PASS (8개 파일 존재 확인)
- data_integrity: PASS
- test_runner: PASS (264 passed in 0.88s)
- tdd_check: PASS (테스트 2개 + 구현 2개 확인)
- pyright_check: WARN (3건 — 기존 테스트 코드 타입 불일치, 이번 변경 무관)
- style_check: PASS (black + isort OK)
- .done 파일: 자동 생성 완료
