[HAN-230] CCR 루틴 타임아웃 제한 해결 — 분석 결과
Summary
“300s 타임아웃”은 스캔 주기(EXECUTION_SCAN_SEC) 혼입.
실제 태스크 timeout은 JARVIS_TIMEOUT_SEC(기본 1800s)이며
.env 실제값 확인 후 상향 가능. 장기 태스크는 분할 설계가 근본 해결.
Context
2026-05-21 Nano(process exit 분석), Asurada(wrap-up) 동시 중단. 이슈 제목의 “300s”는 부정확 — 실제 로그에서 asurada는 672s에서 타임아웃. 원인 분석 및 재발 방지 패턴 수립.
AC 1: 타임아웃 한도 조정 가능 여부
결론: 조정 가능. 설정 위치 명시.
실제 타임아웃 변수 목록
(bridge.py)
| 변수 | 위치 | 기본값 | 역할 |
|---|---|---|---|
JARVIS_TIMEOUT_SEC |
bridge.py:138 |
1800s | Claude subprocess communicate(timeout=...) — 이게
태스크 타임아웃 |
MONITOR_THREAD_TIMEOUT_SEC |
bridge.py:87 |
900s | 스레드 비활성 시 모니터 닫기 |
EXECUTION_SCAN_SEC |
agents/execution.py:14 |
300s | Execution Layer 폴링 주기 (태스크 타임아웃 아님) |
EXECUTION_TIMEOUT_SEC |
agents/execution.py:15 |
3600s | Execution Layer Claude 호출 timeout |
이슈 제목 “300s” 혼입 원인
EXECUTION_SCAN_SEC=300이 .env.example에
노출되어 “300s 타임아웃”으로 오인됨. 실제로 이 값은 5분마다
APPROVED 티켓을 폴링하는 간격이며 태스크를 중단시키지
않는다.
실제 사고 분석
- 로그
wedged-20260521T101246Z.txt확인: asurada turn 1 672s 경과 후in 0 out 0 에러 1건 JARVIS_TIMEOUT_SEC기본값(1800s)보다 낮은 672s 종료 →.env에JARVIS_TIMEOUT_SEC가 실제값으로 오버라이드 되어 있거나 Claude Code CLI 내부 limit 도달 가능성
조정 방법
.env 파일에서:
JARVIS_TIMEOUT_SEC=3600 # 1시간으로 상향
MONITOR_THREAD_TIMEOUT_SEC=1800 # 30분으로 상향 (선택)
주의: Claude Code CLI(subprocess)가 자체 내부
timeout을 가질 수 있음. bridge.py의 JARVIS_TIMEOUT_SEC를
올려도 CLI 내부 한도(확인 필요)가 먼저 걸릴 수 있다.
AC 2: 장기 태스크 처리 전략
결론: 혼합 전략 채택 — 즉시 threshold 상향 + 분할 설계 병행.
즉시 조치 (조정)
.env에서 현재JARVIS_TIMEOUT_SEC값 확인 (cat .env | grep TIMEOUT)- 낮게 설정되어 있으면 3600s로 상향
MONITOR_THREAD_TIMEOUT_SEC도JARVIS_TIMEOUT_SEC보다 크게 설정
근본 해결 (분할)
문제: /wrap-up, 대량 분석 같은 태스크는
본질적으로 10분+ 소요. timeout을 늘려도 20분 태스크가 생기면 재발.
분할 원칙:
| 태스크 유형 | 현재 | 개선 방향 |
|---|---|---|
/wrap-up |
단일 Claude 턴에서 전체 처리 | Phase 1(캡처) → 중간 저장 → Phase 2(라우팅) → Phase 3(sync) 3단계 분리 |
| 대량 분석 (Nano) | 단일 워커에서 전체 처리 | 소스별 Haiku 서브에이전트 병렬화, 결과 집계는 별도 턴 |
| 코드 구현 (Asurada) | 이미 worktree 단위 분리 | 이슈 분할(sub-issue)로 단위 크기 제어 |
권장 구분선
단일 턴 < 5분 → 그대로 진행
5~15분 예상 → JARVIS_TIMEOUT_SEC 여유
있는지 확인 후 진행
15분+ 예상 → 태스크 분할 설계 또는 Nano 병렬화로 내려야
함
AC 3: 재발 방지 패턴
패턴 1: 태스크 시작 시 시간 예산 명시
긴 태스크 프롬프트에 추가:
Budget: complete within 8 minutes. If approaching time limit, save partial results and stop cleanly.
패턴 2: /wrap-up 단계
분리
현재 /wrap-up은 단일 에이전트에서
캡처→라우팅→승격→트리거를 모두 처리. 개선안: 1.
wrap-phase1: 교훈 캡처 + .learnings.md
기록 (3분 이내) 2. wrap-phase2: 라우팅 결정 + memory
업데이트 (3분 이내)
3. wrap-phase3: git push + 세션 prompt 생성 (2분
이내)
각 phase 완료 후 Slack에 중간 보고 → 다음 phase 트리거.
패턴 3: Nano 대형 태스크 분산
Nano가 “N개 소스 조사” 같은 태스크를 받으면: - 소스 1개당 Haiku 서브에이전트 1개 병렬 실행 - 각 서브에이전트 작업 < 3분 설계 - Nano 자신은 집계만 담당 (< 2분)
패턴 4: 모니터 알림 → 조기 저장 훅
bridge.py 모니터가 “elapsed > 500s” 시점에 현재
상태를 state/ 파일에 저장하도록 확장 가능 (선택적 구현, HAN 별도
티켓).
Decisions
| 결정 | 근거 |
|---|---|
즉시: JARVIS_TIMEOUT_SEC=3600 상향 권고 |
현재 기본값 1800s인데 672s에 중단 → .env 값 확인 + 여유 확보 |
장기: /wrap-up 3-phase 분리 |
단일 턴 < 5분 원칙 준수, 재발 방지 근본 해결 |
| “300s 타임아웃” 정정 | EXECUTION_SCAN_SEC는 폴링 주기, 태스크를 종료시키지
않음 |
Risks
| 위험 | 영향 | 대응 |
|---|---|---|
| Claude Code CLI 내부 timeout이 실제 원인일 경우 | env 조정해도 재발 | claude --help timeout 옵션 확인,
--max-turns 파라미터 검토 |
| /wrap-up 3-phase 분리 시 중간 단계 실패 | phase 2 이후 미완 메모리 | phase 1 완료 후 Slack 보고 → 사용자가 다음 phase 트리거 |
링크
- Linear: https://linear.app/hangman-lab/issue/HAN-230