
    +i@              	          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mZ ej                  j                  d e ee      j                         j                  j                              Z ee      dz  dz  dz  Z ee      dz  dz  dz  Z ee      dz  dz  d	z  Z ed
      Z ed      Z ee      dz  Z ee      dz  dz  Zej                  j                  dd      Zej                  j                  dd      Zg dZdefdZdefdZdefdZdefdZdefdZdefdZ dedefdZ!dedefdZ"dedefdZ#dedefdZ$dedefdZ%dedefdZ&e!e"e#e$e%e&dZ'd ed!ed"edefd#Z(defd$Z)d%eddfd&Z*d'ed(edeee+e   f   fd)Z,d*eee+e   f   ddfd+Z-eeeeee dZ.de/fd,Z0e1d-k(  r ejd                   e0              yy).u   
update-system-spec.py
시스템 현재 상태를 자동 수집하여 anu-system-spec.md를 업데이트하는 스크립트.
작성자: 카르티케야 (개발4팀 백엔드 개발자)
    N)PathWORKSPACE_ROOTmemoryspecszanu-system-spec.mdz.spec-state-cache.jsonzanu-system-spec-changelog.mdz/home/jay/.claude/skills/z/home/jay/projects/scriptsztask-timers.jsonANU_KEY ANU_CHAT)skillscronservicesprojectsr   
task_statsreturnc                      t         j                         st        dt                t        t         j	                         D  cg c]/  } | j                         s| j                         s$| j                  1 c}       }|t        |      dS c c} w )u2   스킬 디렉토리를 스캔하여 목록 반환.u   스킬 디렉토리 없음: )r   count)	
SKILLS_DIRexistsFileNotFoundErrorsortediterdiris_diris_filenamelen)pr   s     1/home/jay/workspace/scripts/update-system-spec.pycollect_skillsr   (   sh    ">zl KLLZ%7%7%9WQXXZ199;QVVWXFs6{33 Xs   %B(Bc                  @   t         st        d      dddt         dt        g} t        j                  | ddd      }|j
                  d	k7  r3t        d
|j
                   d|j                  j                                t        j                  |j                        }d|iS )u,   cokacdir --cron-list 실행 후 JSON 파싱.u6   ANU_CHAT 환경변수가 설정되지 않았습니다.z/usr/local/bin/cokacdirz--cron-listz--chatz--keyT   capture_outputtexttimeoutr   u   cokacdir 실행 실패 (exit z): 	cron_jobs)r
   
ValueErrorr   
subprocessrun
returncodeRuntimeErrorstderrstripjsonloadsstdout)cmdresultdatas      r   collect_cronr3   0   s    QRR!C ^^	F A:6;L;L:MSQWQ^Q^QdQdQfPghii::fmm$D    c                     t        j                  g dddd      } g }| j                  j                         D ]<  }|j	                         }|s|j                         }|s)|j                  |d          > t        |      t        |      dS )u0   실행 중인 사용자 서비스 목록 파싱.)	systemctlz--userz
list-unitsz--type=servicez--state=runningz
--no-pagerz--no-legendT   r!   r   )running_servicesr   )	r'   r(   r/   
splitlinesr,   splitappendr   r   )r1   r   linepartss       r   collect_servicesr>   H   s    ^^	
 F H((* &zz|

OOE!H%& !'x 03x=IIr4   c                  8   t         j                         st        dt                t        t         j	                         D  cg c];  } | j                         s| j                  j                  d      r0| j                  = c}       }|t        |      dS c c} w )uI   프로젝트 디렉토리 목록 (디렉토리만, 히든/캐시 제외).u"   프로젝트 디렉토리 없음: .)r   r   )	PROJECTS_DIRr   r   r   r   r   r   
startswithr   )r   r   s     r   collect_projectsrC   d   su     "D\N STT|';';'=k!TUTZTZTeTefiTjqvvklH 3x=99 ls   BB4Bc                      t         j                         st        dt                t        t         j	                         D  cg c]  } | j                         s| j                  ! c}       }|t        |      dS c c} w )u   scripts/ 파일 목록.u"   스크립트 디렉토리 없음: )r   r   )SCRIPTS_DIRr   r   r   r   r   r   r   )r   r   s     r   collect_scriptsrF   l   s`    "D[M RSSk&9&9&;Kqyy{affKLGW66 Ls   A;A;c                     t         j                         st        dt                t         j                  d      5 } t	        j
                  |       }ddd       j                  di       }t        |t              rt        |j                               }nt        |t              r|}ng }t        |      }t        d |D              }|D cg c]-  }t        |j                  d      t        t        f      s)|d   / }}|rt        |      t        |      z  nd}|rt        |      nd}	|rt!        |      nd}
||t#        |d	      t#        |	d	      t#        |
d	      d
S # 1 sw Y   xY wc c}w )u   task-timers.json 통계 계산.u   task-timers.json 없음: utf-8encodingNtasksc              3   J   K   | ]  }|j                  d       dk(  sd  yw)status	completed   N)get).0ts     r   	<genexpr>z%collect_task_stats.<locals>.<genexpr>   s     K!AEE(O{,JAKs   ##duration_secondsg           )total_taskscompleted_tasksavg_duration_secmax_duration_secmin_duration_sec)TASK_TIMERSr   r   openr-   loadrP   
isinstancedictlistvaluesr   sumintfloatmaxminround)fr2   	tasks_raw	task_listtotalrN   rR   	durationsavg_durationmax_durationmin_durations              r   collect_task_statsrp   t   sJ   ";K= IJJ			7		+ qyy| "%I)T"))+,		It	$			NEKyKKI09q1ZN`Hadginco=p%&qIq8AC	NS^3sL%.3y>CL%.3y>CL $!,2!,2!,2 %  rs   E *E-8E- E*r2   c                 v    d| d    dg}| d   D ]  }|j                  d| d        dj                  |      S )N   **총 r   u   개 스킬**
r   - ``
)r;   join)r2   linesss      r   render_skillsry      sM    d7m_N34E(^ !s1#QZ !99Ur4   c                 t   | j                  dg       }|syt        |t              rxdt        |       dg}|D ]R  }t        |t              r+|j                  dt        j                  |d       d       >|j                  d| d       T d	j                  |      S d
t        j                  |dd       dS )Nr%   u   _등록된 cron job 없음_rr   u   개 cron job**
rs   F)ensure_asciirt   ru   z```json
rU   )indentr{   z
```)	rP   r^   r`   r   r_   r;   r-   dumpsrv   )r2   jobsrw   jobs       r   render_cronr      s    88K$D,$#d)$456 	+C#t$s4::c#F"GqIJs3%q\*		+
 yytzz$quEFeLLr4   c                     | j                  dg       }|syd| d    dg}|D ]  }|j                  d| d        dj                  |      S )	Nr8   u*   _실행 중인 사용자 서비스 없음_u   **실행 중: r   u   개**
rs   rt   ru   rP   r;   rv   )r2   svcsrw   rx   s       r   render_servicesr      s`    88&+D;d7m_G45E !s1#QZ !99Ur4   c                     | j                  dg       }|syd| d    dg}|D ]  }|j                  d| d        dj                  |      S )	Nr   u   _프로젝트 없음_rr   r   u   개 프로젝트**
rs   rt   ru   r   )r2   projsrw   r   s       r   render_projectsr      s`    HHZ$E&d7m_$89:E !s1#QZ !99Ur4   c                     | j                  dg       }|syd| d    dg}|D ]  }|j                  d| d        dj                  |      S )	Nr   u   _스크립트 없음_rr   r   u   개 파일**
rs   rt   ru   r   )r2   r   rw   rx   s       r   render_scriptsr      s_    hhy"%G&d7m_N34E !s1#QZ !99Ur4   c                     dt         dt        fd}ddd| d    dd	| d
    d| d   rd| d
   | d   z  dz  ddndd || d          dd || d          dd || d          dg}dj                  |      S )Nrx   r   c                     t        t        |       d      \  }}t        |d      \  }}|r| d| d| dS |r| d| dS | dS )N<   u   시간 u   분 u   초)divmodrc   )rx   msechs       r   fmt_secz"render_task_stats.<locals>.fmt_sec   sc    A#3a}1Ss$se3//SSE%%c{r4   u   | 항목 | 값 |z|------|-----|u   | 총 작업 수 | rV   z |u   | 완료된 작업 | rW   u   | 완료율 | d   z.1fz% |u   | 완료율 | N/A |u   | 평균 소요시간 | rX   u   | 최대 소요시간 | rY   u   | 최소 소요시간 | rZ   ru   )rd   strrv   )r2   r   rw   s      r   render_task_statsr      s    5 S  

d=12"5
%6 78; M" T"34T-5HHLSQQTU&
"740B+C#D"ERH
"740B+C#D"ERH
"740B+C#D"ERHE 99Ur4   contentsectionnew_bodyc                     d| d}d| d}| j                  |      }| j                  |      }|dk(  s|dk(  rd| d| d| d}| |z   S | d|t        |      z    }| |d }	|dz   |z   dz   |	z   S )uw   
    섹션 마커 사이의 내용을 new_body로 교체.
    마커가 없으면 파일 끝에 섹션을 추가.
    z
<!-- AUTO:z
:START -->z:END -->z

ru   N)findr   )
r   r   r   start_marker
end_marker	start_idxend_idxblockbeforeafters
             r   update_section_in_specr      s    
  y
3LgYh/J\*Ill:&GB'R-|nB8*B:,bI 4y3|#445FGHED=8#d*U22r4   c                      t         j                         r6	 t         j                  d      5 } t        j                  |       cd d d        S i S # 1 sw Y   i S xY w# t
        $ r Y i S w xY w)NrH   rI   )
CACHE_FILEr   r\   r-   r]   	Exception)rh   s    r   
load_cacher     si    	'2 $ayy|$ $ I	$ I  	I	s.   A A	A AA A 	A'&A'statec                     t         j                  j                  dd       t         j                  dd      5 }t	        j
                  | |dd       d d d        y # 1 sw Y   y xY w)	NTparentsexist_okwrH   rI   FrU   )r{   r|   )r   parentmkdirr\   r-   dump)r   rh   s     r   
save_cacher     sT    D48	w	/ :1		%q9: : :s   AA%	old_state	new_statec           
         i }t         D ]6  }| j                  |      }|j                  |      }||d| dg||<   5||k(  r;g }dD ]  }t        |t              r|xs i j                  |g       ng }t        |t              r|xs i j                  |g       ng }	t	        t        |	      t        |      z
        }
t	        t        |      t        |	      z
        }|
D ]  }|j                  d| d| d        |D ]  }|j                  d| d| d         |s||k7  r|j                  d| d       |s2|||<   9 |S )u\   
    섹션별로 변경 항목 설명 목록을 반환.
    변경 없으면 빈 dict.
    rt   u   ` 섹션 신규 생성)r   r   r   r8   u   ` 추가: `u   ` 삭제: `u   ` 데이터 변경)SECTIONSrP   r^   r_   r   setr;   )r   r   changesr   oldnewmsgslist_keyold_listnew_listaddedremoveditems                r   detect_changesr   !  sl   
 %'G $mmG$mmG$;3?"#G9,B CDGG#:M 	>H8B38M	rx4SUH8B38M	rx4SUH3x=3x=89ES]S]:;G >azTF!<=> >azTF!<=>	> s
KK!G9$678#GG5$8 Nr4   r   c                    t         j                   j                         j                  d      }d| dg}| j                         D ]#  \  }}|D ]  }|j	                  d| d|         % |j	                  d       t
        j                  j                  dd       d}t
        j                         r/t
        j                  d	
      5 }|j                         }d d d        t
        j                  dd	
      5 }|j                  dj                  |      dz   |z          d d d        y # 1 sw Y   PxY w# 1 sw Y   y xY w)Nz%Y-%m-%d %H:%Mz## [u   ] 변경 내역z- [z] r	   Tr   rH   rI   r   ru   )datetimenowstrftimeitemsr;   CHANGELOG_FILEr   r   r   r\   readwriterv   )r   r   rw   r   r   msgexistingrh   s           r   append_changelogr   L  s/   





!
*
*+;
<CC5()E  1 	1CLL3wir#/0	11 
LLt<H  ' 2 	 avvxH	  
		S7		3 4q			% 4'(234 4	  	 4 4s   	D)9'D5)D25D>c                  .   g } i }t        d       t        D ]#  }	 t        |          }|||<   t        d|        % |st        dt
        j                         yt               }t        ||      }|st        d       | sd	S d
S t        dt        |j                                       t        j                  j                  dd       t        j                         r0t        j                  d      5 }|j!                         }d d d        nd}|D ]%  }||vrt#        |   ||         }	t%        ||	      }' t        j                  dd      5 }|j'                         d d d        t        dt         d       i ||}
t)        |
       t+        |       t        dt,                | sd	S d
S # t        $ rB}| j	                  | d|        t        d| d| t
        j                         Y d }~d }~ww xY w# 1 sw Y   xY w# 1 sw Y   xY w)Nu/   [update-system-spec] 데이터 수집 시작...z  [OK] z: z	  [FAIL] )fileu9   [update-system-spec] 모든 수집 단계 실패. 종료.rU   u@   [update-system-spec] 변경 없음 - 파일 업데이트 생략.r   rO   u$   [update-system-spec] 변경 감지: Tr   rH   rI   u:   # Anu System Spec

_자동 생성된 시스템 명세서_
r   z[update-system-spec] u    업데이트 완료.u2   [update-system-spec] 변경 로그 기록 완료: )printr   
COLLECTORSr   r;   sysr+   r   r   r`   keys	SPEC_FILEr   r   r   r\   r   	RENDERERSr   r   r   r   r   )errorsr   r   r1   er   r   rh   r   bodymerged_states              r   mainr   m  s*   FI 

;< ?	?(*F!'IgGG9%&	? IPSPZPZ[ IY	2GPQq%A%	0glln1E0F
GH 4$7^^W^- 	ffhG	 	 R  A)#!)G"45('4@	A 
g	. !		!),A
BC .i-9-L| W	>~>N
OP1!![  	?MMWIRs+,IgYb,3::>>	?*	 	 s/    F13G?H1	G<:7G77G<?HH__main__)3__doc__r   r-   osrer'   r   pathlibr   environrP   r   __file__resolver   _WORKSPACE_ROOTr   r   r   r   rA   rE   r[   r   r
   r   r_   r   r3   r>   rC   rF   rp   ry   r   r   r   r   r   r   r   r   r   r`   r   r   r   rc   r   __name__exit r4   r   <module>r      s     	 	  
  **..!13tH~7M7M7O7V7V7]7]3^_!H,w69MM	/"X-7:RR
o&1G;>\\-.
)*?#i/?#h.1CC **..B
'::>>*b) O4 4d 0J$ J8:$ :7 7D H  Md Ms M$ 3 $ 3  # D S 8 #	3C 3# 3 3 36D :d :t :#d #t #S$s)^8L #V4d3S	>2 4t 40   $
8"c 8"v zCHHTV r4   