# task-911.1 완료 보고서: Phase 5 토큰 회계 통합 + 모니터링

**담당**: 다그다 (dev3-team 팀장)
**날짜**: 2026-03-24
**검증 레벨**: normal

---

## SCQA

**S**: Phase 2(보안 기반, pytest 32건)와 Phase 3(auto_orch 코어, pytest 32건)이 완료되어 자동화 오케스트레이터의 토큰 추적 및 모니터링 통합을 위한 전제 조건이 충족된 상태다.

**C**: 토큰 사용량 추적, 임계값 경고, 스텝 타임아웃 감지 기능이 미구현이어서 일일 토큰 소비 가시성이 없고, 비정상 세션(2시간+ 실행)을 자동 감지할 수 없다.

**Q**: token_ledger.py 확장(세션 토큰 추정, 사용량 요약, 임계값 경고)과 auto_orch.py 확장(Telegram 경고, stale 태스크 감지, health.json 토큰 정보 포함)을 구현하고, 6개 검증 기준을 통과할 수 있는가?

**A**: token_ledger.py +64 LOC, auto_orch.py +194 LOC, test_phase5.py 601 LOC 구현 완료. pytest 84건(Phase 2: 16 + Phase 3: 32 + Phase 5: 20 + Phase 3 기존 16) 전건 통과. pyright 0 에러. Telegram 경고 중복 방지, health.json v1.1 토큰 정보 포함, stale 태스크 감지 모두 동작 확인.

---

## 생성/수정 파일 목록

- `orchestrator/token_ledger.py` — 확장 (+64 LOC): 3개 메서드 + 3개 상수 추가
- `orchestrator/auto_orch.py` — 확장 (+194 LOC): 2개 함수 신규, 3개 함수 수정, 4개 상수 추가
- `orchestrator/tests/test_phase5.py` — 신규 (601 LOC): 20건 테스트

수정 금지 파일 준수:
- `orchestrator/event_bus.py` — 미수정
- `orchestrator/pipeline_validator.py` — 미수정
- `scripts/` — 미수정
- `dashboard/` — 미수정

---

## 테스트 결과 (정량적 증거)

**Phase 5 pytest**: 20/20 passed (0.17s)

- TestTokenLedgerPhase5: 8/8 PASS
  - Sonnet 세션(600초) → 36,000 토큰 추정 확인
  - Opus 세션(팀장 team_id, 120초) → 12,000 토큰 (Sonnet 7,200 대비 67% 높음)
  - 0초 세션 → 0 토큰
  - get_daily_usage_summary: 450,000/1,000,000 → percentage 45.0% 확인
  - 빈 레저 → 0/1,000,000 → 0.0%
  - check_warning_threshold: 700K→False, 800K→True, 900K→True
- TestTelegramAlert: 4/4 PASS
  - 정상 발송(mock) → True + alerts_sent.json 기록
  - 중복 방지: 동일 날짜+타입 → 두 번째 False
  - ANU_BOT_TOKEN 미설정 → False
  - 날짜 변경 시 재발송 가능 → True
- TestStaleTaskCheck: 2/2 PASS
  - 3시간 running 태스크 2개 감지 + 30분 태스크/완료 태스크 필터링
  - stale 없을 때 빈 리스트
- TestHealthJsonExtension: 2/2 PASS
  - token_usage 포함 시 version "1.1" 확인
  - token_usage=None 시 기존 포맷 하위호환
- TestCmdStatusExtension: 2/2 PASS
  - "토큰 사용량" 섹션 출력 확인
  - "경고 임계값" 텍스트 출력 확인
- TestCmdScanIntegration: 2/2 PASS
  - 80% 초과 시 send_telegram_alert("token_warning") 호출 확인
  - stale 태스크 존재 시 send_telegram_alert("stale_task_*") 호출 확인

**Phase 2+3 회귀**: 64/64 passed (0.57s) — 회귀 없음

**pyright**: 0 errors, 0 warnings, 0 informations (3 파일)

**black + isort**: 3 files would be left unchanged — 포매팅 준수

---

## 6개 검증 기준 달성 현황

1. [x] DAILY_HARD_LIMIT 80% 도달 시 Telegram 경고 발송 (mock 테스트): TestCmdScanIntegration 통과
2. [x] health.json에 token_usage 포함 확인: TestHealthJsonExtension 통과 (version "1.1")
3. [x] cmd_status 출력에 토큰 사용량 포함: TestCmdStatusExtension 통과
4. [x] 경고 중복 방지 (같은 날 동일 경고 재발송 안 함): TestTelegramAlert::test_dedup 통과
5. [x] task-timers.json 데이터와 token_ledger.json 정합성: check_stale_tasks가 task-timers.json 데이터를 정확히 파싱 (start_time 키, "tasks" 래핑 지원)
6. [x] pyright 0 에러, pytest 전건 통과 (Phase 2+3 회귀 포함): 84/84 PASS, pyright 0 에러

---

## 발견 이슈 및 해결

### 자체 해결 (4건)

1. **Opus/Sonnet rate 분기 미구현** — 초기 구현이 모든 세션을 Sonnet rate로 추정. task spec이 Opus 5,000/Sonnet 3,000 분기를 요구하므로, team_id에 "팀장"이 포함되면 Opus rate 적용하도록 수정. (`token_ledger.py:117-118`)

2. **task-timers.json "tasks" 래핑 키 미처리** — 실제 task-timers.json은 `{"tasks": {...}}` 형식이지만 check_stale_tasks가 flat dict만 처리. 양 형식 모두 지원하도록 수정. (`auto_orch.py:430-435`)

3. **테스트 데이터 키 불일치** — 테스트가 `started_at` 키를 사용했지만 실제 task-timers.json은 `start_time` 키 사용. 테스트를 실제 데이터 형식에 맞게 수정.

4. **cmd_scan 통합 테스트 LEDGER_PATH monkeypatch 누락** — 테스트가 STATE_DIR만 monkeypatch하고 LEDGER_PATH를 누락하여 cmd_scan이 실제 파일을 읽음. monkeypatch 추가하여 해결.

### 범위 외 미해결 (0건)

---

## 구현 상세

### token_ledger.py 추가 API

- `TOKENS_PER_MINUTE_OPUS = 5000` / `TOKENS_PER_MINUTE_SONNET = 3000` / `CONSERVATIVE_MULTIPLIER = 1.2`
- `estimate_session_tokens(team_id, duration_seconds)`: 팀장 Opus(5000/min) vs 팀원 Sonnet(3000/min) x 1.2 보수적 계수
- `get_daily_usage_summary()`: `{"today", "limit", "remaining", "percentage"}` dict 반환
- `check_warning_threshold(threshold=0.8)`: daily_total >= threshold * DAILY_HARD_LIMIT

### auto_orch.py 추가 API

- `send_telegram_alert(message, alert_type)`: Direct Telegram API, alerts_sent.json 중복 방지
- `check_stale_tasks()`: task-timers.json 스캔, STALE_TASK_RUNNING_SECONDS(7200초) 초과 감지
- `update_health(...)`: token_usage 파라미터 추가, version "1.1" 갱신
- `cmd_status()`: 토큰 사용량 + 경고 임계값 섹션 출력 추가
- `cmd_scan()`: 토큰 80% 경고 + stale 태스크 경고 + health.json 토큰 정보 갱신

### health.json v1.1 구조

```json
{
  "last_tick": "2026-03-24T11:30:00",
  "active_pipelines": 1,
  "errors_last_hour": 0,
  "token_usage": {
    "today": 450000,
    "limit": 1000000,
    "remaining": 550000,
    "percentage": 45.0
  },
  "version": "1.1"
}
```

---

## TDD 사이클 기록

1. **RED**: 모리건이 test_phase5.py 20개 테스트 작성 → 4개 실패 (미구현 + 불일치)
2. **GREEN**: 루가 token_ledger.py + auto_orch.py 구현 → 16/20 PASS
3. **통합 수정**: 다그다(팀장)가 4개 실패 원인 분석 후 구현+테스트 수정 → 20/20 PASS
4. **REFACTOR**: black + isort 포매팅 적용

---

## 셀프 QC 체크리스트

- [x] 1. 다른 파일 영향: event_bus.py, pipeline_validator.py 미수정. update_health 시그니처 변경은 하위호환(token_usage=None 기본값)
- [x] 2. 엣지 케이스: 0초 세션→0토큰, 빈 레저→0%, alerts_sent.json 미존재→빈 dict, task-timers.json 미존재→빈 리스트
- [x] 3. 작업 지시 일치: 6개 검증 기준 전건 달성
- [x] 4. 에러 처리: JSON 파싱 실패 시 빈 기본값, Telegram API 실패 시 False 반환
- [x] 5. 테스트 커버리지: 20건이 모든 신규 함수/메서드의 정상/경계/실패 경로 커버
- [x] 6. 이슈 해결: 4건 모두 직접 해결, 미해결 0건
