
    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mZ ddlmZ  ej                  dej                        df ej                  dej                        df ej                  dej                        d	f ej                  d
ej                        df ej                  dej                        df ej                  dej                        df ej                  dej                        df ej                  dej                        df ej                  d      dfg	ZdddddddZ ej                  dej                        ZddhZdee   dedefdZdedefd Zdededz  fd!Zdedefd"Zd#edededz  fd$Zd0ded%edz  dee   fd&Zd'ee   defd(Zd'ee   d)edefd*Zd'ee   d)edefd+Zd'ee   d)edefd,Zdej:                  fd-Zd1d.Ze d/k(  r e        yy)2u   
stash_audit.py — Git stash 출처 추적 진단 도구 (read-only)

spec: memory/specs/stash-origin-audit.md
task: task-2570

절대 금지: git stash pop / drop / clear / push
허용: git stash list, git stash show
    N)datetime)Pathzpre[-_]task[-_\s]pre-taskzWIP:\s*pre[-_]taskzfinish[-_]task[-_]quarantine
quarantinezother[-_]files[-_]stashother-fileszother[-_]tasks?[-_]dirtyznon[-_]task[-_]scope[-_]dirtyzfinish[-_]taskfinish-taskzfinish[-_]stashz
^WIP on \wwipzfinish-task.shu*   pre-task (수동 또는 pre_push_guard.py)u   수동 git stashunknown)r   r   r   r   r	   r
   z\[?(task-\d+(?:\+\d+)?)\]?listshowargscwdreturnc                     | r4| d   dk(  r,t        |       dkD  r| d   nd}|t        vrt        d| d      t        j                  dg| z   |dd	      }|j
                  dk7  ry|j                  j                         S )
uF   git 명령 실행. stash pop/drop/clear/push 호출 시 즉시 중단.r   stash    z#[stash_audit] FORBIDDEN: git stash u    — read-only 원칙 위반gitT)r   capture_outputtext)lenALLOWED_GIT_STASH_SUBCOMMANDSRuntimeError
subprocessrun
returncodestdoutstrip)r   r   subresults       */home/jay/workspace/scripts/stash_audit.py_run_gitr"   ;   s    Q7"TQd1gB335cU:VW  ^^	$	F A==      messagec                 J    t         D ]  \  }}|j                  |       s|c S  y)u+   spec §5 패턴 매칭으로 source 결정.r
   )SOURCE_PATTERNSsearch)r$   patternsources      r!   _classify_sourcer*   R   s+    * >>'"M r#   c                 V    t         j                  |       }|r|j                  d      S dS )u$   task-NNNN 또는 task-NNNN+N 추출.r   N)
TASK_ID_REr'   groupr$   ms     r!   _extract_task_idr0   Z   s'    '"A1771:$$r#   c                 l   t        j                  d|       }|r|j                  d      j                         S t        j                  d|       }|r|j                  d      j                         S t        j                  d|       }|r|j                  d      j                         S | j                         S )u   
    stash 메시지에서 reason 텍스트 추출.
    - 'On main: ...' 에서 On main: 제거
    - 'WIP on main: SHA ...' 에서 SHA 이후 텍스트 추출
    - '[task-NNNN][source=X][reason=Y]' 포맷이면 reason 값 추출
    z\[reason=([^\]]+)\]r   zWIP on \S+:\s+[0-9a-f]+\s+(.*)z(?:On \S+:\s*)(.*))rer'   r-   r   matchr.   s     r!   _extract_reasonr4   `   s     			('2Awwqz!! 	2G<Awwqz!! 	&0Awwqz!!==?r#   indexc                 R    t        dddd|  dg|      }|r|j                         S y)u/   stash@{N} reflog에서 timestamp 추출 시도.logz--format=%ciz-1zstash@{}r   N)r"   r   )r5   r   raws      r!   _get_stash_timestampr;   y   s8    
	r&:;C yy{r#   limitc                    t        ddg|       }|sg S |j                         }||d| }g }|D ]  }t        j                  d|      }|st	        |j                  d            }|j                  d      j                         }t        |      }	t        |      }
t        |      }t        j                  |	d      }t        ||       }|j                  ||
|	||||d	        |S )
u}   
    git stash list 파싱 → 구조화된 stash 항목 목록 반환.
    실데이터 변경 없음 (list만 호출).
    r   r   r9   Nzstash@\{(\d+)\}:\s*(.*)r      r
   )r5   task_idr)   reasoncaller_script	timestampraw_message)r"   
splitlinesr2   r3   intr-   r   r*   r0   r4   
CALLER_MAPgetr;   append)r   r<   r:   linesentriesliner/   r5   rC   r)   r?   r@   rA   rB   s                 r!   parse_stash_listrL      s    
 GV$#
.C	NNEfuG 
HH/6AGGAJggaj&&(!+.";/ -"vy9(4	"  !.&*
	

4 Nr#   rJ   c                     i }| D ]  }|d   }|j                  |d      dz   ||<   ! t        |       |t        j                         j	                  d      dS )u)   카테고리별 집계 및 요약 생성.r)   r   r   seconds)timespec)totalcount_by_sourcegenerated_at)rG   r   r   now	isoformat)rJ   rQ   esrcs       r!   	summarizerW      sh    &(O ?k.223:Q>?
 W* 00)0D r#   summaryc           
      *   g }|j                  d       |j                  d       |j                  d|d           |j                  d|d    d       |j                  d       |j                  d	       t        |d
   j                         d       D ]&  \  }}d|z  }|j                  d|dd|dd|        ( |j                  d       |j                  d       |j                  d       dddddddddd }|j                  |       |j                  d       | D ]K  }|d   xs d}|d   }	t        |	      dkD  r|	dd dz   }	|j                  |d    dd|dd|d   dd|	        M |j                  d       d!j	                  |      S )"u    사람 읽기 좋은 표 형식.zN==============================================================================zGit Stash Origin Audit Reportu   생성 시각: rR   u   총 stash: rP      개r   u   [ 카테고리별 집계 ]rQ   c                     | d    S Nr    xs    r!   <lambda>zformat_table.<locals>.<lambda>       aPQdU r#   key#z  z<15 z>3u   개  u   [ 상세 목록 ]zN------------------------------------------------------------------------------IDXz>4r?   z<14r)   r@   --   N*   ...r5   
rH   sorteditemsr   join)
rJ   rX   rI   rV   cntbarhdrrU   r?   r@   s
             r!   format_tablers      s   E	LL	LL01	LL?7>#:";<=	LL;ww/045	LL	LL-.7#45;;=?S 8SCir#c!C85678 
LL	LL$%	LL2Jb3r(3r(
DC	LL	LL 
I,%#8v;CR[5(Fz"oR}Bq{3.?r&J	

 
LL99Ur#   c                 <    || d}t        j                  |dd      S )u   JSON 출력.)rX   rJ   Fr>   )ensure_asciiindent)jsondumps)rJ   rX   payloads      r!   format_jsonrz      s&     G ::gE!<<r#   c                 R   g }|j                  d       |j                  d       |j                  d|d           |j                  d|d    d       |j                  d       |j                  d       |j                  d       |j                  d	       |j                  d
       t        |d   j                         d       D ]  \  }}|j                  d| d| d        |j                  d       |j                  d       |j                  d       |j                  d       |j                  d       | D ]V  }|d   xs d}|d   }t        |      dkD  r|dd dz   }|d   xs d}|j                  d|d    d| d|d     d| d!| d       X d"j	                  |      S )#u   Markdown 출력 (보고서용).z# Git Stash Origin Audit Reportr   u   - **생성 시각**: rR   u   - **총 stash**: rP   rZ   u   ## 카테고리별 집계z| source | count |z|--------|------:|rQ   c                     | d    S r\   r]   r^   s    r!   r`   z!format_markdown.<locals>.<lambda>   ra   r#   rb   z| `z` | z |u   ## 상세 목록z/| idx | task_id | source | reason | timestamp |z/|----:|---------|--------|--------|-----------|r?   rg   r@   2   N/   rj   rB   z| r5   z | `z` | `r)   z | rk   rl   )	rJ   rX   rI   rV   rp   rU   r?   r@   tss	            r!   format_markdownr      s   E	LL23	LL	LL()@(ABC	LL$WW%5$6c:;	LL	LL,-	LL	LL%&	LL%&7#45;;=?S -Ss3%tC5+,-	LL	LL#$	LL	LLBC	LLBC 
I,%#8v;CR[5(F{^"s7D	q{m4xs2$bQ	

 99Ur#   c                     t        j                  dd      } | j                  dddd       | j                  d	d
dd       | j                  dddd d       | j                  dddd d       | j                  dddt        d d       | S )Nzstash_audit.pyuJ   Git stash 출처 추적 진단 도구 (read-only). pop/drop 절대 금지.)progdescriptionz--jsonoutput_json
store_trueu   JSON 형식으로 출력)destactionhelpz
--markdownoutput_markdownu+   Markdown 형식으로 출력 (보고서용)z--outout_pathPATHu*   파일에 저장 (지정 없으면 stdout))r   metavardefaultr   z--workspace	workspaceu2   git workspace 경로 (기본: 현재 디렉토리)z--limitr<   Nu)   최대 N개만 분석 (기본: 무제한))r   r   typer   r   )argparseArgumentParseradd_argumentrE   )parsers    r!   build_parserr     s    $$`F '	   :	   9   A   8   Mr#   c                     t               } | j                         }|j                  r-t        t	        |j                        j                               }nt        t	        j                               }t        ||j                        }t        |      }|j                  rt        ||      }n%|j                  rt        ||      }nt        ||      }|j                  rdt	        |j                        }|j                   j#                  dd       |j%                  |d       t'        d| t(        j*                         y t'        |       y )N)r   r<   T)parentsexist_okzutf-8)encodingu   [stash_audit] 결과 저장: )file)r   
parse_argsr   strr   resolver   rL   r<   rW   r   rz   r   r   rs   r   parentmkdir
write_textprintsysstderr)r   r   r   rJ   rX   outputout_files          r!   mainr   9  s    ^FD ~~T^^,4467	
O	 9DJJ?G G Wg.			 '2gw/ }}&dT:FW5-hZ8szzJfr#   __main__)N)r   N)!__doc__r   rw   r2   r   r   r   pathlibr   compile
IGNORECASEr&   rF   r,   r   r   r   r"   r*   r0   r4   rE   r;   dictrL   rW   rs   rz   r   r   r   r   __name__r]   r#   r!   <module>r      s     	  
   RZZ$bmm4jARZZ%r}}5zBRZZ/?NRZZ*BMM:MJRZZ+R]];]KRZZ0"--@-PRZZ!2==1=ARZZ"BMM2MBRZZ&$ $"#<
 RZZ5r}}E
 "( 0 !49 !3 !3 !.c c %c %cDj %S S 2 # #* (# (cDj (DJ (^tDz d $$t* t  <=d =d =s =T$Z $ 3 F'h-- 'T@ zF r#   