# task-1108.1 완료 보고서: autoresearch 인증 방식 수정 (SDK → claude -p CLI)

## SCQA

**S**: autoresearch 시스템이 Anthropic Python SDK(`anthropic.Anthropic`, `client.messages.create`)를 직접 호출하여 모델 실행, mutation 생성, 채점을 수행하고 있다. task-1104.1에서 OAuth 인증을 적용했으나 401 에러 발생.

**C**: Anthropic API가 OAuth 토큰을 지원하지 않아 SDK 직접호출이 실패. 반면 `claude -p` CLI는 내부적으로 OAuth를 처리하여 정상 동작한다.

**Q**: SDK 호출을 `claude -p` CLI 래퍼로 교체하여 인증 문제를 해결하고 기존 기능을 유지할 수 있는가?

**A**: `call_claude()` 공용 래퍼를 `claude_runner.py`에 생성하고, 4개 모듈(skill_executor, mutator, judge, runner)에서 SDK 호출을 CLI 래퍼로 교체. pytest 169건 전체 통과, pyright 에러 0건, black/isort 준수.

## 생성/수정 파일

### 신규 (1건)
- `scripts/autoresearch/claude_runner.py` — `call_claude()`, `estimate_tokens()` 공용 래퍼
- `scripts/autoresearch/tests/test_claude_runner.py` — 래퍼 단위 테스트 13건

### 수정 (8건)
- `scripts/autoresearch/skill_executor.py` — `load_auth()`, `_create_client()`, `anthropic` import 제거. `execute_skill()` → `call_claude()` 사용
- `scripts/autoresearch/mutator.py` — `anthropic`/`TextBlock`/`_create_client` import 제거. `generate_mutation()` → `call_claude()` 사용
- `scripts/autoresearch/judge.py` — 동일 패턴. `judge_output()` → `call_claude()` 사용
- `scripts/autoresearch/runner.py` — `load_auth` import 및 auth 로딩 블록 제거, `api_key`/`auth` 파라미터 전체 제거
- `scripts/autoresearch/tests/test_skill_executor.py` — `TestLoadAuth`, `TestCreateClient` 클래스 제거. `TestExecuteSkill` mock 대상을 `call_claude`로 변경
- `scripts/autoresearch/tests/test_mutator.py` — `TestGenerateMutation` mock을 `call_claude`로 변경
- `scripts/autoresearch/tests/test_judge.py` — `TestJudgeOutput` mock을 `call_claude`로 변경
- `scripts/autoresearch/tests/test_runner.py` — auth/api_key 관련 mock 및 인자 전체 제거

## 테스트 결과
- **pytest**: 169 passed, 0 failed (0.37s)
- **pyright**: 0 errors, 0 warnings (5개 소스 파일)
- **black/isort**: 5 files unchanged (준수)

## 주요 설계 결정

1. **토큰 추정**: `claude -p`는 토큰 사용량 미제공 → `chars/4` 추정 (`estimate_tokens()`)
2. **CLAUDECODE 환경변수**: `env.pop("CLAUDECODE", None)`으로 중첩 세션 방지
3. **모델 분리 유지**: mutation/execution → `claude-sonnet-4-6`, judge → `claude-haiku-4-5-20251001`
4. **`load_env_key()` 유지**: deprecated이지만 일반 유틸리티로 하위호환 유지
5. **`--max-turns 1`**: 도구 사용 없이 단순 응답만 반환

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **runner.py auth 전파 코드 잔존** — `run_round()`와 `run()` 내부의 모든 `auth=`, `api_key=` 인자 및 로딩 로직 완전 제거
2. **test_runner.py 대규모 auth mock** — `TestRunRoundAuth` 클래스 제거 + 6개 호출부의 `api_key=` 인자 제거
3. **토큰 카운팅 인터페이스 변경** — SDK의 정확한 토큰 카운트 → chars/4 추정으로 변경. changelog.py의 토큰 기록 로직은 기존대로 유지 (추정값이더라도 동일 필드에 저장)

## 셀프 QC 체크리스트

- [x] 1. 영향 파일: skill_executor.py, mutator.py, judge.py, runner.py + 5개 테스트 파일
- [x] 2. 엣지 케이스: 빈 system prompt(None), subprocess 타임아웃, 비정상 exit code 처리
- [x] 3. 작업 지시와 정확히 일치 (6개 요구사항 + 제거 대상 4항목 모두 반영)
- [x] 4. 에러 처리: RuntimeError(stderr 포함), TimeoutExpired 전파, execute_skill 에러 dict 반환
- [x] 5. 테스트: 169/169 통과, 새 래퍼 13건 + 기존 테스트 전체 갱신
- [x] 6. 발견 이슈 3건 모두 직접 해결
- [x] 7. SOLID 원칙 준수: claude_runner.py는 SRP(CLI 래퍼 단일 책임), OCP(향후 다른 모듈도 import만으로 사용 가능)
- [x] 8. 인터페이스 변경: execute_skill, generate_mutation, judge_output 시그니처에서 api_key/auth 제거 → 호출부(runner.py) 모두 갱신

## QC 자동 검증 결과

- **overall**: PASS (8 PASS, 0 FAIL, 4 SKIP)
- file_check: PASS (5/5 파일 존재, 보고서 4,253 bytes)
- data_integrity: PASS
- test_runner: PASS (94 passed in 0.21s)
- pyright_check: PASS (0 errors, 0 warnings)
- style_check: PASS (black OK, isort OK)
- critical_gap: PASS
- spec_compliance: PASS
- duplicate_check: PASS (최대 유사도 10.3%)
