
    Zi\J              
          d 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 ddlZ ee      j!                         j"                  Z ee      ej(                  vr"ej(                  j+                  d ee             ddlmZ ej2                  j5                  dd      Z	 ej(                  j+                  de       ddlmZ 	 dd	lm Z!  e e
d            Z$ e ee      dz  dz        Z% ejL                  d      Z' ejL                  d      Z( ejL                  d      Z)d*dedz  de*eef   fdZ+dededededz  ddf
dZ,dededdfdZ-dededdfdZ.defdZ/dede*fd Z0d!edede#fd"Z1dede*fd#Z2deddfd$Z3dededz  fd%Z4d&ede#fd'Z5d+d(Z6e7d)k(  r e6        yy# e$ r dZY w xY w# e$ r ddlZ"d
ede#fdZ!Y w xY w),uC   팀장 → 아누 완료 통보 스크립트 (체인 인식 버전)    N)datetime	timedeltatimezone)Path)format_notification_messageWORKSPACE_ROOTz/home/jay/workspace)sync_task_completion)is_valid_task_id_with_legacysreturnc                 @    t        t        j                  d|             S )Nz^task-\d+(?:\.\d+)?$)bool_re_fallbackmatch)r   s    L/home/jay/workspace/.worktrees/task-2487+1-dev2/scripts/notify-completion.py_is_valid_task_idr   #   s    L&&'>BCC    	   )hourslogszdone-protocol.logz^[a-z0-9\-]+$z^[a-zA-Z0-9/_\-\.]+$z^(normal|critical|security)$env_filec                 8   | 	t          d} i }t        |       }|j                         s|S 	 |j                  d      j	                         D ]  }|j                         }|r|j                  d      r'|j                  d      r|t        d      d j                         }d|vrY|j                  d      \  }}}|j                         }|j                         }t        |      dk\  r|d	   |d
   k(  r|d	   dv r|dd
 }|s|||<    	 |S # t        $ r Y |S w xY w)uV  `.env.keys` 파일을 파싱하여 환경변수 딕셔너리를 반환한다.

    지원 형식:
        export KEY=VALUE
        KEY=VALUE
        export KEY="VALUE"   (따옴표 제거)
        export KEY='VALUE'   (따옴표 제거)

    주석(#)과 빈 줄은 무시한다.
    파일이 없으면 빈 딕셔너리를 반환한다.
    Nz
/.env.keysutf-8encoding#zexport =   r   )"'   )
r   r   exists	read_text
splitlinesstrip
startswithlen	partitionOSError)r   resultpathraw_linelinekey_values           r   load_env_keysr2   .   s.    $%Z0F>D;;=8CCE 	$H>>#D4??3/y)C	N,-335$ NN3/MCE))+CKKME5zQ58uRy#8U1X=Sa#s!	$( M  Ms   CD D 	DDteam	task_filelevelnext_task_idc                    t         j                  |       s.d| }t        d| t        j                         t        |      t        j                  |      s.d|}t        d| t        j                         t        |      t        j                  |      s.d|}t        d| t        j                         t        |      |:t        |      s.d|}t        d| t        j                         t        |      yy)uF  dispatch 인자를 검증한다. 패턴 불일치 시 ValueError를 발생시킨다.

    Args:
        team: 팀 이름 (예: "dev1-team")
        task_file: 태스크 파일 경로
        level: 우선순위 ("normal" | "critical" | "security")
        next_task_id: 다음 태스크 ID (예: "task-566.2") 또는 None
    u7   dispatch 인자 검증 실패 - team 패턴 불일치: zERROR: fileu<   dispatch 인자 검증 실패 - task_file 패턴 불일치: u8   dispatch 인자 검증 실패 - level 허용값 초과: Nu?   dispatch 인자 검증 실패 - next_task_id 패턴 불일치: )	_RE_TEAMr   printsysstderr
ValueError_RE_TASK_FILE	_RE_LEVELr   )r3   r4   r5   r6   msgs        r   _validate_dispatch_argsrB   Z   s     >>$GxPuoCJJ/oy)LYMZuoCJJ/o??5!H	RuoCJJ/o(9,(GOP\O_`uoCJJ/o )Hr   task_idmessagec                 \   t        j                  t              j                         }d| d|  d| d}	 t	        t
              }|j                  j                  dd       t        t        |      dd	      5 }|j                  |       d
d
d
       y
# 1 sw Y   y
xY w# t        $ r Y y
w xY w)u3   done-protocol.log에 상태 전이를 기록한다.[z] [notify-completion] z: 
Tparentsexist_okar   r   N)r   nowKST	isoformatr   DONE_PROTOCOL_LOGparentmkdiropenstrwriter*   )rC   rD   tsr.   log_pathfs         r   log_protocolrX   }   s    	c		$	$	&Brd(	G9B?D)*dT:#h-w7 	1GGDM	 	 	 s0   AB 8B
B BB B 	B+*B+c                    t        t         d|  d      }	 |j                  j                  dd       |j	                  |d       t        | dt        |       d       y
# t        $ r}t        | d	|        Y d
}~y
d
}~ww xY w)us   완료 메시지를 파일로 저장한다. 아누가 .done 감지 시 이 파일을 읽어 그대로 전달한다./memory/events/z.completion.txtTrH   r   r   u   .completion.txt 저장 완료 (z chars)u   .completion.txt 저장 실패: N)r   r   rP   rQ   
write_textrX   r(   r*   )rC   rD   completion_filees       r   _save_completion_messager^      s    n-_WI_UVOE$$TD$A""7W"=W ?G~WUV EW ?sCDDEs   A	A! !	B*A>>Bc                      t         j                  j                  d      } | s0t        dt        j
                         t	        j                  d       | S )u=   ANU_KEY를 환경변수에서 가져온다. 없으면 종료.COKACDIR_KEY_ANUu   [FATAL] COKACDIR_KEY_ANU 환경변수가 설정되지 않았습니다. 아누 세션 인증키가 필요합니다. 해결: 'source /home/jay/workspace/.env.keys'를 실행하거나 '--anu-key <key>' 옵션으로 직접 전달하세요.r8   r"   )osenvirongetr;   r<   r=   exit)r/   s    r   get_anu_keyre      sA    
**..+
,CE 	
 	Jr   c                    dt          ddd| g}	 t        j                  |ddd      }|j                  dk(  rt	        j
                  |j                        S 	 d	d	d
d
dS # t        j                  t        j                  f$ r Y ,w xY w)u?   chain_manager.py check 호출하여 체인 소속 여부 확인python3/chain_manager.pycheck	--task-idT   capture_outputtexttimeoutr   FN)in_chainis_lastchain_idr6   	r   
subprocessrun
returncodejsonloadsstdoutTimeoutExpiredJSONDecodeErrorrC   cmdr+   s      r   check_chain_statusr~      s     	
+,CDtRP!::fmm,, "
 %TSWXX %%t';';< s   AA #BBchat_idc           	         t         j                  j                  d      }|st        dd       yd| d}| |dd}t	        d	      D ]  }	 t        j                  ||d
      }|j                  dk(  r y|j                  dk(  rI| |d}t        j                  ||d
      }|j                  dk(  r yt        dd|j                           y|j                  dk(  r;t        |j                  j                  dd            }	t        j                  |	       t        dd|j                           y# t
        j                  $ r8}
t        dd|dz    d|
        t        j                  d|z         Y d}
~
1d}
~
ww xY w)uB   직접 Telegram Bot API 호출 (토큰 0, Claude 세션 미생성)ANU_BOT_TOKEN u,   WARN: ANU_BOT_TOKEN 미설정, 알림 스킵Fzhttps://api.telegram.org/botz/sendMessageMarkdown)r   rn   
parse_mode   
   )rw   ro      Ti  )r   rn   u"   WARN: Telegram fallback도 실패 i  zRetry-After   zWARN: Telegram API u&   WARN: Telegram 전송 실패 (attempt r"   ): r   N)ra   rb   rc   rX   rangerequestspoststatus_codeintheaderstimesleepRequestException)r   rD   	bot_tokenurlpayloadattemptrespfallbackfallback_respretry_afterr]   s              r   send_telegram_notificationr      sr   

/IRGH(<
@C!7*MG8 #	#==7B?D3&3&'.@ (c" M ,,3R#EmF_F_E`!ab3&!$,,"2"2=!"DE

;'243C3C2DEF##, 	 (( 	#EgPQk]RUVWUXYZJJq'z""	#s1   
'D13;D10D1A	D1D11E<-E77E<c                    dt          ddd| g}	 t        j                  |ddd      }|j                  dk(  rt	        j
                  |j                        S 	 d	d
iS # t        j                  t        j                  f$ r Y d	d
iS w xY w)u?   chain_manager.py next 직접 호출하여 다음 Phase dispatchrg   rh   nextrj   T<   rl   r   actionerrorrs   r|   s      r   dispatch_next_phaser      s     	
+,CDtRP!::fmm,, " g %%t';';< gs   AA #BBc           	          dt          dd| g}	 t        j                  |ddd       y# t        j                  $ r+ t	        d|  dt          d	|  t
        j                  
       Y yw xY w)u   task-timer end 호출rg   z/memory/task-timer.pyendTrk   rl   uW   WARNING: task-timer end 호출이 30초 초과로 타임아웃되었습니다 (task_id=u)   ). 수동으로 실행하세요: python3 z/memory/task-timer.py end r8   N)r   rt   ru   rz   r;   r<   r=   )rC   r}   s     r   end_task_timerr      s     	
/0	C
s4dBG$$ 
efmen o55C4DD^_f^gi	

s   ) ;A'&A'c                    	 t        t         d      }|j                         rXt        j                  |j                  d            }|j                  di       j                  | i       }|j                  d      S 	 y# t        $ r Y yw xY w)u0   task-timers.json에서 task_id로 team_id 조회z/memory/task-timers.jsonr   r   tasksteam_idN)r   r   r#   rw   rx   r$   rc   	Exception)rC   
timer_filedata	task_datas       r   get_team_id_from_taskr      s    ^,,DEF
::j22G2DED"-11'2>I==++    s   A9A> >	B
	B
r   c                 J   	 ddl m}  || d       y# t        $ r Y n6t        $ r+}t	        d|  d| t
        j                         Y d}~y	d}~ww xY w	 t        t         d
      }|j                         sy	t        |dd      5 }t        j                  |      }ddd       n# 1 sw Y   nxY w| j                  di       v rt        j                  t         j"                        j%                  d      }d|d   |    d<   ||d   |    d<   |j'                  d      }t        |dd      5 }t        j(                  ||dd	       ddd       n# 1 sw Y   nxY w|j+                  |       y	 y	# t        $ r+}t	        d|  d| t
        j                         Y d}~y	d}~ww xY w)uZ   bot-activity.json의 봇 상태를 idle로 설정

    Returns:
        성공 여부
    r   )set_bot_statusidleTu#   WARNING: set_bot_idle 실패 (team=r   r8   NFz /memory/events/bot-activity.jsonrr   r   botsz%Y-%m-%dT%H:%M:%SZstatussincez.tmpwr   )indentensure_asciiu1   WARNING: set_bot_idle 직접 구현 실패 (team=)utils.bot_activityr   ImportErrorr   r;   r<   r=   r   r   r#   rR   rw   loadrc   r   rL   r   utcstrftimewith_suffixdumpreplace)r   r   r]   bot_activity_filerW   r   utc_now	temp_files           r   set_bot_idler     s   
5w'  3G9CsC#**U
 N#33S!TU '')#S7; 	 q99Q<D	  	  	  dhhvr**ll8<<099:NOG.4DL!(+-4DL!'* *55f=Iiw7 A1		$!%@A A A/0 + 	  A'#aSQX[XbXbcsh    	AA!AA"E. 7E. B$	E. $B-)BE. +E	E. EE. .	F"7!FF"c            	      N   t        j                  d      } | j                  dd       | j                  dt        j                  j                  dd      	       | j                  d
d 	       | j                         }|j                  xs  t        j                  j                  dd      }t        rK	 t        |j                        }|j                  d      r$t        d|d    d|j                  dd              t        |j                        }|j                  d      r|j                  d      smt        d|j                   d|j                  d       d       t        |j                  d|j                  d       d       t!        |j                        }t        dt#        j$                  |d              |j                  d      dk(  r|j                  d      }|j                  d       }|j                  d!d"      }	|j                  d      }
|r|r	 t'        |||	|
       t+               }i t        j                  |}d$t,         d%d&|d'|d(|	g}|
r|j/                  d)|
g       	 t1        j2                  |d*d*d+|,      }|j4                  d-k7  r?t        |j                  d.       t        d/|j                   t        j                         nt        d0|        n	 |j                  dd3      }t9        t,         d4|j                   d5      }t9        t,         d6|j                   d7      }d }|j;                         r&	 t#        j<                  |j?                  d89            }tE        |j                  ||      }|jG                  d:|j                   d;d:|j                   d<| d=d>      }tI        |j                  |       tK        |jL                  |      rt9        t,         d6|j                   d?      }|jN                  jQ                  d*d*@       	 t        jR                  tU        |      t        jV                  t        jX                  z  t        jZ                  z        }t        j\                  |       t        |j                  dA       n|j                  d      rCt        d|j                   dC       t        |j                  dD|j                  d       d       n/t        dE|j                   dF       t        |j                  dG       t9        t,         d4|j                   d5      }t9        t,         d6|j                   d7      }d }|j;                         r&	 t#        j<                  |j?                  d89            }tE        |j                  ||      }tI        |j                  |       tK        |jL                  |      rt9        t,         d6|j                   d?      }|jN                  jQ                  d*d*@       	 t        jR                  tU        |      t        jV                  t        jX                  z  t        jZ                  z        }t        j\                  |       t        |j                  dA       ta        |j                        }|rb	 tc        |      rt        |j                  dH| d       n:t        |j                  dI| d       t        dJ| dt        j                         y y t        |j                  dN       y # t        $ r)}t        d| t        j                         Y d }~Vd }~ww xY w# t(        $ r t        |j                  d#       Y y w xY w# t0        j6                  $ r5 t        |j                  d1       t        d2t        j                         Y w xY w# t"        j@                  tB        f$ r Y sw xY w# t^        $ r t        |j                  dB       Y ww xY w# t"        j@                  tB        f$ r Y w xY w# t^        $ r t        |j                  dB       Y w xY w# t        $ rD}t        |j                  dK|        t        dL| dM| t        j                         Y d }~y d }~ww xY w)ONu/   팀장 → 아누 완료 통보 (체인 인식))descriptionrC   u   작업 ID (예: task-381.1))helpz	--chat-idCOKACDIR_CHAT_ID
6937032012)defaultz	--anu-keyr`   r   updatedz[TODO] u   건 업데이트: detailsu   WARNING: todo sync 실패: r8   rp   rq   z[CHAIN] u   : 체인 중간 Phase (chain=rr   )zchain middle dispatch (chain=u   [CHAIN] dispatch 결과: F)r   r   dispatchr4   r3   r5   normalu4   dispatch 인자 검증 실패 (셸 인젝션 방지)rg   z/dispatch.pyz--teamz--task-filez--levelrj   Tr   )rm   rn   ro   envr   u   dispatch 실패u   ERROR: dispatch 실패: u(   [CHAIN] dispatch.py 호출 성공: team=u   dispatch 타임아웃u   ERROR: dispatch.py 타임아웃unknownz/memory/reports/z.mdrZ   z.doner   r   z**u    완료 보고**u    완료 보고** (chain: u!   ). 다음 Phase 자동 위임됨.r"   z.done.notifiedrH   u   .done.notified 마커 생성u#   .done.notified 마커 이미 존재u0   : 체인 마지막 Phase → 텔레그램 알림z"chain last telegram notify (chain=z	[NOTIFY] u'   : 일반 작업 → 텔레그램 알림z independent task telegram notifyu   bot idle 전환 성공 (team=u   bot idle 전환 실패 (team=u&   WARNING: bot idle 전환 실패 (team=u   bot idle 전환 예외: u&   WARNING: bot idle 전환 예외 (team=r   u&   team_id 없음, bot idle 전환 스킵)2argparseArgumentParseradd_argumentra   rb   rc   
parse_argsanu_keyr	   rC   r;   r   r<   r=   r~   rX   r   rw   dumpsrB   r>   r2   r   extendrt   ru   rv   rz   r   r#   rx   r$   r{   r*   _format_notification_messager   r^   r   r   rP   rQ   rR   rS   O_CREATO_EXCLO_WRONLYcloseFileExistsErrorr   r   )parserargsr   sync_resultr]   
chain_infodispatch_resultr4   r3   r5   r6   env_keys
merged_envdispatch_argvr+   rr   _report_path
_done_path
_done_datarD   notified_pathfdr   s                          r   mainr   8  s   $$1bcF
	(EF


1<@      D llDbjjnn-?DG 	F.t||<Ky)I 677I+//ZcegJhIijk
 $DLL1J ~~j!*..*C&CJNNS]D^C__`abLL+JNN:,F+GqI	
 .dll;)$**_SX*Y)Z[\ x(J6'++K8I"&&v.D#'':E*..y9LT+D)ULQ )?7

7h7
 %&l3!	!  !((+|)DE'^^%'+! "&F ((A-$ LL- 6v}}oF!$
  HOP  >>*i8~..>t||nCPQ^,ODLL>OP

!ZZ
(<(<g(<(NO
 /t||\:V//./7zAbc

 	!w7%dllG< N#3?4<<.P^!_`M  &&td&CRWWS/bii1G"++1UVT\\+IJ >>*%HT\\N*Z[\4Z^^J5O4PPQR
 Idll^+RST'IJ~..>t||nCPQ^,ODLL>OP

!ZZ
(<(<g(<(NO
 /t||\:V w7%dllG< N#3?4<<.P^!_`M  &&td&CRWWS/bii1G"++1UVT\\+IJ
 $DLL1G	]G$T\\-J7)ST+UVT\\-J7)ST+UV>wiqIPSPZPZ[ W 	T\\#KLy  	F/s3#**EE	F: "  /efR "00  / 9 ZZ ( (('2 " # RT\\+PQR, (('2  # RT\\+PQR  	])A!'EF:7)3qcJQTQ[Q[\\	]s   3A
\& !] 4A6^  %_ 'A:_+ 7%` A:`1 .Aa &	]/]]]=<]= A___('_(+```.-`.1aa	b$ :bb$__main__)N)r   N)8__doc__r   rw   ra   reshlexrt   r<   r   r   r   r   pathlibr   r   __file__resolverP   _SCRIPTS_DIRrS   r,   insertreport_utilsr   r   rb   rc   r   utils.todo_syncr	   r   utils.task_id_parserr
   r   r   r   rM   rO   compiler:   r?   r@   dictr2   rB   rX   r^   re   r~   r   r   r   r   r   r   __name__ r   r   <module>r      s   I   	 	   
  2 2   H~%%'..|CHH$HHOOAs<() T 02GH HHOOA~&4DV
 yq!"^,v58KKL  2::&'

23BJJ67	)C$J )$sCx. )X 
     *	 
 
 F
# 
 
 
Ec EC ED ES Y Y Y&   c  d  F  $
C 
D 
$
3 
3: 
*# *$ *ZrMj zF a      DDS DT DDs$   0"F5 G 5F?>F?GG