# task-1411.1 완료 보고서

**S**: dispatch.py가 org-structure.json과 bot_settings.json 두 곳에서 모델 설정을 관리하지만, 두 파일 간 정합성 검증이 없고, bot_settings.json은 git 미추적 상태여서 변경 이력 추적이 불가능하다.

**C**: 2026-03-29 dev3에서 org-structure는 sonnet인데 bot_settings는 opus로 설정되어 혼란이 발생했으며, 모델 결정 우선순위가 명문화되지 않아 원인 파악이 어려웠다.

**Q**: 설정 파일 간 모델 불일치를 자동 감지하고, bot_settings.json의 변경 이력을 추적할 수 있는가?

**A**: dispatch.py에 `_validate_model_consistency()` (정합성 검증)과 `_sync_bot_settings()` (사본 동기화) 함수를 추가하여, 디스패치 성공 시 자동으로 모델 일치 검증 + 민감정보 마스킹 사본 저장이 수행된다. pytest 167건 전체 통과(신규 9건 포함), pyright 신규 에러 0건.

## 산출물

- `/home/jay/workspace/dispatch.py` (수정: 2개 함수 추가 + dispatch/composite 연동)
- `/home/jay/workspace/tests/test_dispatch.py` (수정: 2개 테스트 클래스 9건 추가)
- `/home/jay/workspace/memory/bot_settings_sync.json` (신규: 초기 동기화 파일)

## 변경 상세

### 문제 1: 모델 불일치 방지 — `_validate_model_consistency(team_id)`
- org-structure.json에서 team_id의 lead.model 탐색 (직접 매칭 + sub_teams 하위 탐색)
- bot_settings.json에서 해당 봇의 models[chat_id] 읽기
- 불일치 시 WARNING 로그 출력, 디스패치는 bot_settings.json 기준 유지
- dispatch() 성공 시 자동 호출 (dispatch.py:1472)

### 문제 2: bot_settings.json git 미추적 해결 — `_sync_bot_settings()`
- bot_settings.json 읽기 → token 필드를 `***REDACTED***`로 마스킹 → workspace에 저장
- 저장 경로: `/home/jay/workspace/memory/bot_settings_sync.json`
- dispatch() 및 _dispatch_composite() 성공 시 자동 호출 (dispatch.py:1477, 1095)
- git 추적 대상이 되어 변경 이력 추적 가능

### 문제 3: 모델 결정 우선순위 문서화
- **실제 API 호출 모델**: bot_settings.json의 `models[chat_id]` 기준 (변경 불가)
  - `_read_bot_models()` → `_find_available_bot(required_model)` 에서 필터링
  - cokacdir에 전달되는 `--key` 값이 봇을 결정하고, 해당 봇의 bot_settings 모델이 사용됨
- **대시보드/조직도 표시**: org-structure.json의 lead.model 기준 (표시용)
- **model_router**: task_desc 기반 권장 모델 결정 → `_find_available_bot(required_model)` 에서 해당 모델의 봇만 선택
- 3/29 dev3 opus 기록 원인: bot_settings.json이 opus로 설정되어 있었기 때문 (org-structure와 무관하게 bot_settings 기준 실행)

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **dev3 모델 불일치 현황 확인** — 현재 시점에서 dev3 org-structure와 bot_settings 모두 `claude-opus-4-6`으로 일치 확인 (이전에 수정된 것으로 보임)
2. **import copy 위치** — `_sync_bot_settings()` 내부에 `import copy` 지연 로드 사용. dispatch.py의 기존 패턴(함수 내 지연 import)과 일치하므로 그대로 유지
3. **_validate_model_consistency에서 both 모델이 빈 문자열일 때** — consistent=True로 반환 (검증 불가능한 경우는 차단하지 않음). 로그에 "확인 불가" 표시

## 테스트 결과

- 기존 테스트: 158건 통과 (회귀 0건)
- 신규 테스트: 9건 통과
- 전체: 167건 통과, 실패 0건
- pyright: 신규 에러 0건 (기존 reportMissingImports만 존재)

## 모델 사용 기록

- 아누비스(백엔드): dispatch.py 함수 구현 / sonnet
- 토트(테스터): 테스트 작성 / sonnet
