
    i                       d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z
ddlZ
ddlmZmZmZ ddlmZ  ej"                  d      Z ej&                  ej(                  d        e ed	
            Z eej,                  j/                  dd            Zedz  dz  dz  Zej,                  j/                  dd      Zej,                  j/                  dd      Z eej,                  j/                  dd            Zej,                  j/                  dd      dk(  Zej,                  j/                  dd      Zd$d%dZ d&dZ!d'dZ"d'dZ#edfd(dZ$d)dZ%d*d Z&d+d,d!Z'd-d"Z(e)d#k(  r ejT                   e(              yy).up  daily_digest.py — 매일 09:00 어제 자동 머지(Tier 1) 다이제스트 + 랜덤 10% 회장 검토.

데이터 소스: memory/audit/auto-merge.log (JSONL append-only)
출력: Telegram 단일 메시지 카드
환경변수:
  ANU_CONFIRM_BOT_TOKEN, ANU_CONFIRM_CHAT_ID, WORKSPACE_ROOT, GH_REPO
  DIGEST_SAMPLE_RATE (기본 0.1), DIGEST_DRY_RUN (=1 발송 안 함)
    )annotationsN)datetime	timedeltatimezone)Pathdaily_digestz1%(asctime)s [%(levelname)s] %(name)s: %(message)s)levelformat	   )hoursWORKSPACE_ROOTz/home/jay/workspacememoryauditzauto-merge.logANU_CONFIRM_BOT_TOKEN ANU_CONFIRM_CHAT_IDDIGEST_SAMPLE_RATEz0.1DIGEST_DRY_RUN01GH_REPOzJonghyukJeon/workspacec                    | t        j                  t              } | j                  dddd      }|t	        d      z
  }||fS )u    어제 00:00 ~ 오늘 00:00 KST.r   )hourminutesecondmicrosecond   )days)r   nowKSTreplacer   )r   today_startyesterday_starts      E/home/jay/workspace/.worktrees/task-2463-dev6/scripts/daily_digest.py_yesterday_range_kstr%   $   sE    
{ll3++1Qqa+HK!I1$55OK''    c                   | j                         st        j                  d|  d       g S g }	 | j                  dd      5 }|D ]:  }|j	                         }|s	 |j                  t        j                  |             < 	 ddd       |S # t        j                  $ r"}t        j                  d|        Y d}~xd}~ww xY w# 1 sw Y   |S xY w# t        $ r#}t        j                  d|        Y d}~|S d}~ww xY w)	uV   JSONL audit log 파싱. 미존재/손상 시 빈 리스트 반환 (graceful fallback).u   audit log 미존재: u    — 빈 결과 반환rutf-8)encodingu'   audit log 라인 파싱 실패 (skip): Nu   audit log 읽기 실패: )existsloggerinfoopenstripappendjsonloadsJSONDecodeErrorwarningOSErrorerror)pathrecordsfrawlineexcs         r$   _parse_audit_logr=   -   s    ;;=+D61GHI	G8YYsWY- 	T Tyy{TNN4::d#34T	T N	 ++ TNN%LSE#RSST	T N  80677N8s_   C C$B CC C B=8C=CCC
C C 	C>C99C>c                ^   g }| D ]  }|j                  d      dk7  r|j                  d      dk7  r-|j                  dd      }	 t        j                  |      }|j                  |j	                  t
              }||cxk  r|k  sn |j                  |        |S # t        $ r Y w xY w)u;   어제 KST 사이 + tier=tier1 + outcome=merged 만 필터.tiertier1outcomemerged	timestampr   tzinfogetr   fromisoformatrE   r!   r    
ValueErrorr0   r8   r#   r"   filteredr(   ts_strtss          r$   _filter_yesterday_tier1_mergedrN   B   s    H 55=G#55x'{B'	''/Byy ZZsZ+ b.;.OOA O	  		   7B  	B,+B,c                ^   g }| D ]  }|j                  d      dk7  r|j                  d      dk7  r-|j                  dd      }	 t        j                  |      }|j                  |j	                  t
              }||cxk  r|k  sn |j                  |        |S # t        $ r Y w xY w)u1   어제 escalated tier3 (인간 게이트 대기).r?   tier3rA   	escalatedrC   r   rD   rF   rJ   s          r$   _filter_tier3_pendingrS   V   s    H 55=G#55{*{B'	''/Byy ZZsZ+ b.;.OOA O	  		rO   c           	         | sg S t        j                  t        |       |z        }t        dt	        |t        |                   }|dk(  rg S ||nt        j                         }|j                  | |      S )uU   랜덤 sample. ceil(len*rate). 1건 미만은 0건. rng 주입 가능 (테스트용).r   )mathceillenmaxminrandomRandomsample)rB   raterngn_rngs        r$   _sample_for_reviewra   j   sf    			#f+$%AAs1c&k"#AAv	!$#fmmoD;;vq!!r&   c                6   d| ddg}| r|j                  dt        |        d       | dd D ]  }|j                  dd	      }|j                  d
d	      }t        |j                  d      t              rt        |j                  dg             nd	}|j                  d| d|j                  dd       d| d| d	        t        |       dkD  r0|j                  dt        |        d       n|j                  d       |j                  d       |r|j                  dt        t        dz         dt        |       d       |D ]R  }|j                  dd	      }|j                  dd	      }	|	r|	d	k7  rdt         d|	 nd}
|j                  d| d|
        T n|j                  d       |j                  d       |j                  dt        |       d       |dd  D ]'  }|j                  d|j                  dd	       d!       ) d"j                  |      S )#u!   Telegram 카드 텍스트 생성.u*   ★ 자동 머지 일일 다이제스트 ()r   u   Tier 1 자동 머지: u   건N   task_id?diff_loc
diff_filesz- z: Lv.r	   r   z, u   파일, LOCu	   ... (총 u   건)u   Tier 1 자동 머지: 0건u   ★ 랜덤 검토 대상 (d   z%): 	pr_numberzhttps://github.com/z/pull/u   (PR 없음)u   : 회장 검토 권장 — u   ★ 랜덤 검토 대상: 0건u&   ★ Tier 3 인간 게이트 (대기): 
   u   : 회장 명시 승인 필요
)	r0   rW   rG   
isinstancelistintSAMPLE_RATEr   join)rB   reviewspendingdate_strlinesr(   tidrg   filesprurls              r$   _format_cardr{   v   s   9(1ErJE-c&k]#>? 	]A%%	3'CuuZ-H4>quu\?RTX4YClB/0_bELL2cU%gs(;'<BugXhZWZ[\		]
 v;LL9S[M6712	LL1#k#o2F1GtCPWL>Y\]^ 	EA%%	3'C{C(B?AbCi'yrd;UbCLL2cU"=cUCD		E 	56	LL	LL9#g,sKLSb\ Pr!%%	3/00MNOP 99Ur&   c                   t         s|r|st        j                  d       dd| dS d| d}t        j                  j                  || d      j                  d      }	 t        j                  j                  ||d	
      5 }t        j                  |j                         j                  d            cddd       S # 1 sw Y   yxY w# t        $ r0}t        j                  d|        dt        |      dcY d}~S d}~ww xY w)uK   Telegram sendMessage. dry-run 또는 token 미설정 시 dict로 반환만.zTelegram dry-run modeFT)okdry_runtextzhttps://api.telegram.org/botz/sendMessage)chat_idr   r)   rl   )datatimeoutNu   Telegram 발송 실패: )r}   r6   )DRY_RUNr,   r-   urllibparse	urlencodeencoderequesturlopenr1   r2   readdecode	Exceptionr6   str)r   r   	bot_tokenrz   payloadrespr<   s          r$   _telegram_sendr      s    iw+,d;;(<
@Cll$$$%GHOOPWXG0^^##Cgr#B 	;d::diik009:	; 	; 	; 0/u56c#h//0s<   "C  2B<2	C <CC C 	D%C<6D<Dc                B   |xs t         }t        |       \  }}t        |      }t        |||      }t	        |||      }t        |      }|j                  d      }t        ||||      }	t        |	t        t              }
t        |      t        |      t        |      |	|
|dS )u   다이제스트 1회 실행.

    반환: {"merged_count": N, "reviews": [...], "pending": [...], "card_text": "...", "telegram_result": {...}}
    z%Y-%m-%d)merged_countreviews_countpending_count	card_texttelegram_result	yesterday)	AUDIT_LOGr%   r=   rN   rS   ra   strftimer{   r   CHAT_ID	BOT_TOKENrW   )r   
audit_pathr#   r"   r8   rB   rt   rs   ru   card	tg_results              r$   
run_digestr      s    
 (yJ#7#< O[z*G+G_kRF#G_kJG (G''
3H(;DtWi8I FWW$ r&   c            
         t               } t        t        j                  | j	                         D ci c]  \  }}|dk7  s|| c}}dd             t        d| d   z          yc c}}w )Nr   F   )ensure_asciiindentz
=== Card ===
r   )r   printr1   dumpsitems)resultkvs      r$   mainr      s\    \F	$**v||~Jtq!k9IadJY^gh
ij	
vk2
23 Ks   A& A&__main__)N)r   datetime | Nonereturnztuple[datetime, datetime])r7   r   r   
list[dict])r8   r   r#   r   r"   r   r   r   )rB   r   r]   floatr^   zrandom.Random | Noner   r   )
rB   r   rs   r   rt   r   ru   r   r   r   )r   r   r   r   r   r   r   dict)NN)r   r   r   zPath | Noner   r   )r   rp   )+__doc__
__future__r   r1   loggingrU   osrZ   sysurllib.parser   urllib.requestr   r   r   pathlibr   	getLoggerr,   basicConfigINFOr    environrG   	WORKSPACEr   r   r   r   rq   r   r   r%   r=   rN   rS   ra   r{   r   r   r   __name__exit r&   r$   <module>r      sa   #    	  
   2 2 			>	*   ',,/b cyq!" 02GHI	 7*-==	JJNN2B7	
**...
3BJJNN#7?@
**..)3
/3
6
**..$<
=(*(( :Ebf 	" F04 zCHHTV r&   