
    i5                        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 ej                  j                  d e
 ee      j                         j                  j                              Z e
 ee      dz        dz   ZdZdZd	Zd
Zh dZg dZdedee   fdZdedee   fdZdedee   fdZdedee   fdZdedee   fdZd Zedk(  r e        yy)u   output/ 폴더 구조 검증 스크립트.

사용법:
    python3 scripts/validate-output-structure.py [--output-dir /path/to/output]

기본값: /home/jay/workspace/output/
    N)PathWORKSPACE_ROOToutput/PASSWARNFAILINFO>   briefsdeliverybackgroundsconcept-catalogconcept-samples)zmeta-adsz
google-adsz	naver-ads
output_dirreturnc                 <   g }| j                         D cg c]  }|j                         s| }}|r3|D ]-  }|j                  dt        d|j	                  |        d       / n|j                  dt
        dd       t        D ]  }| |z  }|j                         s|j                         D cg c]  }|j                         s| }}|r3|D ]-  }|j                  dt        d|j	                  |        d       / ||j                  dt
        | dd        t        D ]  }| |z  }|j                         s|j                         D ]  }|j                         r|j                  j                  d      s/|j                         D cg c]  }|j                         s| }	}|	r3|	D ]-  }|j                  dt        d|j	                  |        d       / |j                  dt
        | d	|j                   dd         |S c c}w c c}w c c}w )
uE   루트 및 주요 하위 폴더에 직접 파일이 있는지 검사.
root_filesu!   output/ 루트에 파일 존재: checklevelmessageu&   output/ 루트에 직접 파일 없음u.   주요 하위 폴더 루트에 파일 존재: u    / 루트에 직접 파일 없음angle-u&   angle 폴더 루트에 파일 존재: r   )iterdiris_fileappendr   relative_tor   MAJOR_AD_DIRSexistsis_dirname
startswith)
r   resultspr   fad_dir_namead_dirad_files	angle_dirangle_filess
             R/home/jay/workspace/.worktrees/task-2116-dev1/scripts/validate-output-structure.pycheck_root_filesr+   '   s@   G (//1AQYY[!AJA 	ANN)!!B1==Q[C\B]^	 	%C	
 % k)}}%~~/?!199;A?? !-!%%STUTaTablTmSn#o NN)!"-.NO0 % k)}}) 	I##%Y^^-F-Fx-P&/&7&7&9IQYY[1IKI$ ANN%1%))OPQP]P]^hPiOj'k !-!%&1]!INN3CCc#d		4 NM B0 @6 Js"   HH0HHH%Hc                    	 g t        j                  d      	dt        dt        f 	fd}t        D ]q  } |z  }|j                         s|j                         D ]F  }|j                         r|j                  j                  d      s/ ||| d|j                          H s  dz  }|j                         r||j                         D ]i  }|j                         s|j                  }|t        v r)	j                  |      r;j                  dt        d	| d
|j                          dd       k t        d D              sj                  dt         dd       S )u3   버전 폴더 네이밍 규칙(v01, v02...) 검증.z	^v\d{2,}$r(   context_labelc                    | j                         D ]l  }|j                         s|j                  }|t        v r)j	                  |      r;j                  dt        d| d| d|j                         dd       n y)u0   angle-* 폴더 하위 폴더들을 검사한다.version_namingu    버전 폴더 네이밍 위반 (z): ',   ' — v01, v02... 패턴이 아님 (경로: )r   N)r   r   r    VERSION_FOLDER_EXCEPTIONSmatchr   r   r   )r(   r-   childr    r   r"   version_patterns       r*   check_angle_childrenz2check_version_naming.<locals>.check_angle_childrenz   s    &&( 	E<<>::D00"((.!1!%>}o N  $v &((-(9(9*(E'FaI	
	    r   r   zcampaign-topr/   u0   버전 폴더 네이밍 위반 (campaign-top): 'r0   r1   r   c              3   H   K   | ]  }|d    dk(  xr |d   t         k(    yw)r   r/   r   Nr   .0rs     r*   	<genexpr>z'check_version_naming.<locals>.<genexpr>   s+     Vqz--D!G*2DDVs    "u%   버전 폴더 네이밍 위반 없음)recompiler   strr   r   r   r   r    r!   r2   r3   r   r   r   anyr   )
r   r6   r%   r&   r(   campaign_topr4   r    r"   r5   s
   `       @@r*   check_version_namingrC   u   ss   Gjj.O S , % Ok)}}) 	OI##%Y^^-F-Fx-P {m1Y^^<L,MN	O	O .L!))+ 	E<<>::D00"((.!1!%  $v &((-(9(9*(E'FaI	
	& VgVV)B	
 Nr7   c                     g }g }g }t        j                         D ]L  \  }}}t        |      }|D ]6  }|dk(  r|j                  ||z         |dk(  s#|j                  ||z         8 N t	        |      dk(  r|j                  dt
        dd       nt	        |      dk(  r/|j                  dt        d|d   j                          d       nBd	j                   fd
|D              }	|j                  dt        dt	        |       d|	 d       t	        |      dk(  r|j                  dt        dd       |S d	j                   fd|D              }	|j                  dt        d|	 dd       |S )u5   concept-catalog/concept-samples 중복 위치 검사.r   r   r   concept_catalog_duplicatesu-   concept-catalog 폴더가 존재하지 않음r      u$   concept-catalog 폴더 1개 존재: , c              3   R   K   | ]  }t        |j                                 y wNr@   r   r;   r#   r   s     r*   r=   z3check_concept_catalog_duplicates.<locals>.<genexpr>        Tc!--
";<T   $'u   concept-catalog 폴더가 u    곳에 존재 (1개만 허용): u&   concept-samples 폴더 없음 (정상)c              3   R   K   | ]  }t        |j                                 y wrI   rJ   rK   s     r*   r=   z3check_concept_catalog_duplicates.<locals>.<genexpr>   rL   rM   uR   concept-samples 폴더가 존재함 — concept-catalog로 통합 필요 (위치: r1   )
oswalkr   r   lenr
   r   r   joinr   )
r   r"   catalog_pathssamples_pathsrootdirs_	root_pathd	paths_strs
   `         r*    check_concept_catalog_duplicatesr[      s   GMM, 4dAJ	 	4A%%$$Y]3''$$Y]3		44 =Q5J	
 
]	q	 5A-PQBRB^B^_iBjAkl	
 IITmTT	57M8J7KKklukvw	
 =Q5C	
" N IITmTT	5tu~t  @A  B	
 Nr7   c                    g t        j                  d      dt        dt        ffd}t        D ]q  }| |z  }|j                         s|j                         D ]F  }|j                         r|j                  j                  d      s/ ||| d|j                          H s sj                  dt        dd	       S )
u&   버전 폴더 번호 연속성 검사.z^v(\d{2,})$r(   labelc                 l   g }| j                         D ]Z  }|j                         s
j                  |j                        }|s2|j	                  t        |j                  d                   \ |sy|j                          t        t        |d   |d   dz               }t        t        |      t        |      z
        }|rB|D cg c]  }d|d
 }}	j	                  dt        d| d	d
j                  |       d       y	j	                  dt        d| d|d   dd|d   dd       yc c}w )u:   angle-* 폴더 내 v숫자 폴더 번호 연속성 검사.rF   Nr   v02dversion_continuityu   버전 번호 불연속 (u   ): 누락된 버전 rG   r   u   버전 번호 연속 (z): vz~v)r   r   r3   r    r   intgroupsortlistrangesortedsetr   rR   r   )r(   r]   numsr4   mexpectedmissingnmissing_strsr"   r5   s            r*   check_angle_version_seqz9check_version_continuity.<locals>.check_angle_version_seq   s9   &&( 	-E<<>%%ejj1AC
O,	- 		d1gtBx!|45XT23189Aa#wK9L9NN1!";E7BZ[_[d[deq[rZs t NN1!!7wd473-rRVWYRZ[^Q_` :s   D1r   r   rb   u3   버전 폴더가 존재하는 angle-* 폴더 없음r   )r>   r?   r   r@   r   r   r   r   r    r!   r   r
   )r   rp   r%   r&   r(   r"   r5   s        @@r*   check_version_continuityrq      s    Gjj0O4  B % 
k)}}) 	I##%Y^^-F-Fx-P#-q 01		
 -P	
 Nr7   c                 J   g }t               }t        j                  |       D ]T  \  }}}t        |      }|j                  dk(  s"t        |D cg c]  }||z  	 c}d       dd }|j                  |       V d}	t        j                  |       D ]p  \  }}}
t        |      }||v r|
rt        d t        j                  |      D              }|rB|j                  |       }|j                  dt        d	| d
       d}	r |	s|j                  dt        dd
       |S c c}w )uB   빈 폴더 검사 (concept-catalog 직접 하위 20개는 제외).r   c                     | j                   S rI   )r    )r#   s    r*   <lambda>z%check_empty_folders.<locals>.<lambda>E  s
    aff r7   )keyN   Fc              3   :   K   | ]  \  }}}t        |        y wrI   )bool)r;   rW   	sub_filess      r*   r=   z&check_empty_folders.<locals>.<genexpr>Q  s     Y?1atIYs   empty_foldersu   빈 폴더 발견: r   Tu   빈 폴더 없음)ri   rO   rP   r   r    rh   updaterA   r   r   r
   r   )r   r"   excluded_dirsrU   rV   rW   rX   rY   direct_childrenempty_foundfileshas_any_filerels                r*   check_empty_foldersr   9  s<   G  #uM, 2dAJ	>>..$(,-1Q-$ rO   12 KWWZ0 #dEJ	%YbggiFXYYL++J7!0!%%8#> ###& (.	
 NE .s   D 
c            	         t        j                  d      } | j                  dt        d       | j	                         }t        |j                        }|j                         s9t        t        j                  dd| d             t        j                  d	       g }|j                  t        |             |j                  t        |             |j                  t!        |             |j                  t#        |             |j                  t%        |             t'        d
 |D              }t'        d |D              }|rt(        n|rt*        nt,        }|t/        |      t1        d |D              t1        d |D              t1        d |D              t1        d |D              |d}t        t        j                  |dd             t        j                  |rd	       y d       y )Nu   output/ 폴더 구조 검증)descriptionz--output-diru   검증 대상 디렉토리)defaulthelperroru   디렉토리 없음: )statusr   rF   c              3   4   K   | ]  }|d    t         k(    ywr   Nr	   r:   s     r*   r=   zmain.<locals>.<genexpr>       7!1W:%7   c              3   4   K   | ]  }|d    t         k(    ywr   r9   r:   s     r*   r=   zmain.<locals>.<genexpr>  r   r   c              3   :   K   | ]  }|d    t         k(  sd  ywr   rF   N)r   r:   s     r*   r=   zmain.<locals>.<genexpr>       =!!G**<A=   c              3   :   K   | ]  }|d    t         k(  sd  ywr   r9   r:   s     r*   r=   zmain.<locals>.<genexpr>  r   r   c              3   :   K   | ]  }|d    t         k(  sd  ywr   r   r:   s     r*   r=   zmain.<locals>.<genexpr>  r   r   c              3   :   K   | ]  }|d    t         k(  sd  ywr   )r
   r:   s     r*   r=   zmain.<locals>.<genexpr>  r   r   )r   total_checkspasswarnfailinfodetailsF   )ensure_asciiindentr   )argparseArgumentParseradd_argumentOUTPUT_DIR_DEFAULT
parse_argsr   r   r   printjsondumpssysexitextendr+   rC   r[   rq   r   rA   r	   r   r   rQ   sum)parserargsr   r"   has_failhas_warnoverallr   s           r*   mainr   i  s   $$1OPF
")  
 Ddoo&JdjjG:OPZ|8\]^_GNN#J/0NN'
34NN3J?@NN+J78NN&z23 7w77H7w77HdXT4G G=w===w===w===w==F 
$**V%
:;HH(Q""r7   __main__)__doc__r   r   rO   r>   r   pathlibr   environgetr@   __file__resolveparent_WORKSPACE_ROOTr   r   r   r	   r
   r2   r   rf   dictr+   rC   r[   rq   r   r   __name__ r7   r*   <module>r      s(     	 	 
 **..!13tH~7M7M7O7V7V7]7]3^_o.9:S@    8K K$t* K\DT Dd4j DN< <$t* <~; ;$t* ;|-D -T$Z -`&#R zF r7   