#!/bin/bash # session_health.sh — C40 세션 수명 자동 실측 + hook 게이트 헬스체크 (UserPromptSubmit · 10분 스로틀) # 근거: 2026-08-20 세션 30MB(스크린샷 116장) → 403 socket closed 사망 실측 (BT14) # 기준: 세션 기록 10MB 또는 누적 이미지 30장 도달 시 세션 전환 권고 (권고 기준 — 운영 조정 가능) # 세션 식별: hook stdin JSON의 transcript_path (공식 스키마) — 추정 아닌 실측. 폴백: mtime 최신 # --- 게이트 헬스체크 (fail-open 보완: PreToolUse hook 실패는 침묵 통과되므로 여기서 관측) --- if [ -z "$CLAUDE_PROJECT_DIR" ]; then echo "⚠️ [hook 헬스체크] CLAUDE_PROJECT_DIR 미주입 — hook 체계 전반 무력화 가능 상태. Claude Code 버전·hook 설정 점검 필요" fi GATE="${CLAUDE_PROJECT_DIR:-.}/scripts/auditor_gate.sh" if [ ! -f "$GATE" ]; then echo "⚠️ [hook 헬스체크] auditor_gate.sh 접근 불가($GATE) — C35-9 게이트 침묵 무력화 상태 (fail-open). 경로·클론 상태 점검 필요" fi # --- 스로틀 (10분) --- THROTTLE_DIR="$HOME/.claude/.burningtimes_throttle" THROTTLE="$THROTTLE_DIR/session_health" mkdir -p "$THROTTLE_DIR" now=$(date +%s) last=$(cat "$THROTTLE" 2>/dev/null || echo 0) [ $((now - last)) -lt 600 ] && exit 0 echo "$now" > "$THROTTLE" # --- 현 세션 파일 식별: stdin JSON transcript_path 우선 --- f="" if [ ! -t 0 ]; then stdin_json=$(cat 2>/dev/null) f=$(printf '%s' "$stdin_json" | grep -o '"transcript_path":"[^"]*"' | head -1 | sed 's/.*transcript_path":"//;s/"$//;s/\\\\/\//g') fi # 폴백: mtime 최신 jsonl (C24 단일 세션 전제 — 다중 프로젝트 환경에서는 오판 가능, transcript_path 실패 시에만 사용) if [ -z "$f" ] || [ ! -f "$f" ]; then f=$(ls -t "$HOME"/.claude/projects/*/*.jsonl 2>/dev/null | head -1) fi [ -z "$f" ] || [ ! -f "$f" ] && exit 0 size=$(wc -c < "$f" 2>/dev/null | tr -d ' ') size=${size:-0} size_mb=$((size / 1048576)) imgs=$(grep -c '"type":"image"' "$f" 2>/dev/null | head -1) imgs=${imgs:-0} if [ "$size_mb" -ge 10 ] || [ "$imgs" -ge 30 ]; then echo "⚠️ [C40 세션 수명] 현 세션 기록 ${size_mb}MB · 누적 이미지 ${imgs}장 — 기준(10MB/30장) 도달." echo " → C40 인수인계서 작성 + 다음 세션 첫 프롬프트 템플릿 제공 후 세션 전환 권고" echo " → 근거: 30MB 세션 403 소켓 끊김 사망 실측 (2026-08-20)" elif [ "$size_mb" -ge 7 ] || [ "$imgs" -ge 20 ]; then echo "📏 [C40 세션 수명 예고] 현 세션 기록 ${size_mb}MB · 이미지 ${imgs}장 — 기준(10MB/30장) 접근 중. 스크린샷 검증 최소화(C14-7) 유지" fi exit 0