# task-846.1 완료 보고서

## S - Situation (현재 상황)
multimodel-bot이 Claude Code를 `--output-format text`로 실행할 때, tool 실행 과정(파일 읽기, 셸 명령 등)과 CLAUDE.md 시스템 프롬프트 내용이 Telegram 채팅에 그대로 노출되고 있다. 모든 봇(dev1~dev4)이 동일 구조로 영향받는다.

## C - Complication (문제/변화)
내부 시스템 프롬프트(팀장 역할, 작업 규칙 등)가 사용자에게 노출되면 보안 문제와 UX 저하를 초래한다. Claude/Gemini/Codex 3개 엔진 모두 동일 문제를 갖고 있으며, 각 엔진별 출력 형식이 달라 일관된 해결이 필요하다.

## Q - Question (핵심 질문)
Claude/Gemini의 JSON 출력 형식 전환과 content sanitizer 이중 안전장치를 통해 tool 실행 결과 노출을 완전히 차단할 수 있는가?

## A - Answer (답변/제안)
A안(JSON 파싱)과 B안(content sanitizer)을 모두 구현하여 2중 방어 체계를 완성했다.

**A안 (근본 해결)**: Claude/Gemini의 `--output-format`을 `text` → `json`으로 변경하고, `_parse_json_output()` 메서드로 응답 텍스트만 추출. JSON 파싱 실패 시 원본 텍스트를 그대로 반환하는 fallback 포함.

**B안 (이중 안전장치)**: `sanitize_output()` 함수로 4단계 필터링 파이프라인 구축 — CLAUDE.md 헤더, 시스템 프롬프트 섹션, tool 실행 코드 블록, 20줄 이상 파일 덤프 제거. 필터링 후 빈 응답 방지 로직 포함. call_claude/call_codex/call_gemini 3개 함수 모두에 적용.

pytest 401건 전체 통과(신규 21건 포함). pyright 에러 0건.

---

## 수정/생성 파일 목록

### 수정
- `services/multimodel-bot/engine_v2/cli_runner.py` — `--output-format json` 전환, `_parse_json_output()` 추가, `run_claude()`/`run_gemini()`에 JSON 파싱 적용
- `services/multimodel-bot/engine_v2/content_sanitizer.py` — `sanitize_output()` 함수 및 보조 함수 3개 추가 (`_remove_system_sections`, `_remove_long_code_blocks`, 정규식 패턴 5개)
- `services/multimodel-bot/engine_v2/bot_api.py` — `sanitize_output` import 및 call_claude/call_codex/call_gemini 3개 함수에 적용

### 신규 생성
- `services/multimodel-bot/tests/test_content_sanitizer.py` — sanitize_output TDD 테스트 (10개 케이스)

### 테스트 수정
- `services/multimodel-bot/tests/test_cli_runner.py` — JSON 파싱 테스트 6개 추가
- `services/multimodel-bot/tests/test_bot_api.py` — sanitize 통합 테스트 5개 추가

---

## 테스트 결과

- **전체 테스트**: 401 passed, 0 failed (0.88s)
- **신규 테스트**: 21건 (cli_runner 6 + content_sanitizer 10 + bot_api 5)
- **pyright**: 0 errors, 0 warnings, 0 informations
- **포매팅**: black + isort 적용 완료

---

## 발견 이슈 및 해결

### 자체 해결 (3건)

1. **기존 test_run_gemini_cmd_format 테스트 실패** — Gemini의 기본 출력 형식을 `json`으로 변경하고 JSON 파싱 로직 추가하여 해결
   - 수정: `cli_runner.py:144` output_format 기본값 `"text"` → `"json"`, L155-166 JSON 파싱 추가

2. **시스템 섹션 제거 시 빈 줄 처리 버그** — `_remove_system_sections`에서 시스템 헤더 뒤 빈 줄이 pending_blanks 없이 바로 스킵되어 다음 일반 텍스트까지 누락될 수 있는 문제를 `pending_blanks` 리스트로 보류 후 판단하는 방식으로 해결
   - 수정: `content_sanitizer.py:147-173` pending_blanks 패턴 구현

3. **Codex CLI에 `--output-format` 없음** — Codex CLI는 JSON 출력 형식을 지원하지 않아 A안 적용 불가. B안(sanitize_output)으로 대체 적용
   - 근거: `codex exec` 명령 스펙에 output-format 옵션 없음

---

## 엔진별 적용 현황

- **Claude**: A안(JSON 파싱) + B안(sanitizer) 이중 적용
- **Gemini**: A안(JSON 파싱) + B안(sanitizer) 이중 적용
- **Codex**: B안(sanitizer)만 적용 (JSON 출력 미지원)

---

## 안전장치

- JSON 파싱 실패 → 원본 텍스트 fallback (cli_runner.py `_parse_json_output`)
- 필터링 후 빈 응답 → 원본 반환 (content_sanitizer.py `sanitize_output`)
- 에러/타임아웃 메시지 → sanitize 미적용 (bot_api.py 에러 경로는 sanitize 전에 return)
- DEBUG 레벨 로깅으로 필터링 전/후 길이 차이 추적
