
    i/              
           d Z ddlZddlZddlZddlmZ  ed      Zedz  dz  Zedz  dz  Zde	d	e
dz  fd
Zded	e
fdZ G d d      Zde	dede
de
d	ef
dZdee   d	dfdZd	ee   fdZd	efdZedk(  r ej*                   e              yy)u  
skill-quality-check.py — 전체 스킬 품질 검증 스크립트

검증 항목:
  1. SKILL.md 존재 여부       (FAIL if missing)
  2. Frontmatter 유효성       (WARN if invalid)
  3. evals/ 디렉토리 존재 여부 (INFO if missing)
  4. skill-registry.json 동기화 (WARN if not synced)
  5. eval-axes.json 동기화    (INFO if missing)

판정 기준:
  PASS  — SKILL.md 존재 + frontmatter 유효 + registry 동기화
  WARN  — SKILL.md 존재하지만 frontmatter 불완전 또는 registry 미동기화
  FAIL  — SKILL.md 없음

exit code:
  0 — FAIL 없음 (PASS 또는 WARN만)
  1 — FAIL 하나 이상 존재
    N)Pathz/home/jay/workspace/skillssharedzskill-registry.jsonzeval-axes.jsontextreturnc                   
 | j                         }|r|d   j                         dk7  ryd}t        |dd d      D ]  \  }}|j                         dk(  s|} n |y|d| }i d
g 
fd}|D ]  }d|v r`|j                  d      sO|j                  d	      s> |        |j	                  d      \  }}}	|j                         
|	j                         gg|j                  d
      s|j                  d	      r#
j                  |j                                |j                         s |        |j                         j                  d      
g   |        S )u   
    SKILL.md 내용에서 YAML frontmatter를 파싱한다.
    첫 줄이 '---'로 시작하고 두 번째 '---' 로 끝나는 블록을 추출.
    반환값: dict (필드명 → 값) 또는 None (frontmatter 없음)
    r   z---N   )startc                      mdj                        j                         } | j                  d      r| j                  d      s"| j                  d      r| j                  d      r| dd } | <   d g y )N
"'r   )joinstrip
startswithendswith)rawcurrent_keycurrent_value_linesresults    2/home/jay/workspace/scripts/skill-quality-check.pyflush_currentz(parse_frontmatter.<locals>.flush_current<   so    "))/0668Cs#S(9s#S(9!Bi"%F;     z:  	z  :)
splitlinesr   	enumerater   	partitionappendrstrip)r   linesend_idxilinefm_linesr   key_valr   r   r   s             @@@r   parse_frontmatterr*   $   sX    OOEE!HNN$-GU12Ya0 4::<5 G
 QwHFK%'
!  )4< 4T__T=RO...KCC))+K#&99;-__T"dood&;&#**4::<8 zz|"jjl11#6&(#!)$ OMr   pathc                     	 t        | d      5 }t        j                  |      cd d d        S # 1 sw Y   y xY w# t        t        j                  f$ r i cY S w xY w)Nutf-8encoding)openjsonloadFileNotFoundErrorJSONDecodeError)r+   fs     r   	load_jsonr6   b   sQ    $) 	 Q99Q<	  	  	 t334 	s#   : .	: 7: : AAc                   :    e Zd ZdefdZedefd       ZdefdZy)SkillResultnamec                 t    || _         d| _        d| _        g | _        d| _        d| _        g | _        d| _        y )NF)r9   has_skill_mdfrontmatter_validfrontmatter_issues	has_evalsregistry_syncedregistry_issuesaxes_synced)selfr9   s     r   __init__zSkillResult.__init__o   s@    	"'',-/$%**,!&r   r   c                 P    | j                   sy| j                  r| j                  syy)NFAILWARNPASS)r;   r<   r?   )rB   s    r   verdictzSkillResult.verdicty   s%      %%T-A-Ar   c                 <   | j                   }g }| j                  r|j                  d       n6|j                  d       d| d| j                   ddj	                  |      z   S | j
                  r|j                  d       n>| j                  rdj	                  | j                        nd	}|j                  d
| d       | j                  r|j                  d       n|j                  d       | j                  r|j                  d       n>| j                  rdj	                  | j                        nd}|j                  d| d       | j                  r|j                  d       n|j                  d       d| d| j                   ddj	                  |      z   S )Nu   SKILL.md ✓u   SKILL.md ✗ (파일 없음)[z] u    — z, u   frontmatter ✓z / u   유효하지 않음u   frontmatter ✗ ()u	   evals ✓u	   evals ✗u   registry ✓u   미동기화u   registry ✗ (u   axes ✓u   axes ✗ (평가 축 미정의))rH   r;   r    r9   r   r<   r=   r>   r?   r@   rA   )rB   rH   parts	issue_strs       r   format_linezSkillResult.format_line   s_   ,, LL(LL78wir$))E2TYYu5EEE !!LL*+?C?V?V

4#:#:;\qILL,YKq9: >>LL%LL% LL(<@<P<P

4#7#78VdILL>)A67 LL$LL:;7)2dii[.51AAAr   N)__name__
__module____qualname__strrC   propertyrH   rN    r   r   r8   r8   n   s7    'S '   %BS %Br   r8   
skill_name	skill_dirregistry	eval_axesc                 0   t        |       }|dz  }|j                         |_        |j                  r	 |j                  d      }t        |      }|#d|_        |j                  j                  d       nAd|vs|d   j                         s#d|_        |j                  j                  d       nd	|_        |d
z  j                         |_        | |v rd	|_        n"d|_        |j                  j                  d       | |v |_        |S # t        $ r d}Y w xY w)NzSKILL.mdr-   r.    Fu   frontmatter 없음descriptionu   description 누락Tevalsu	   미등록)r8   is_filer;   	read_textOSErrorr*   r<   r=   r    r   is_dirr>   r?   r@   rA   )rU   rV   rW   rX   r   skill_md_pathcontentfms           r   check_skillrd      s'    $F 
*M'//1F	#--w-?G w':',F$%%,,-AB"$B},=,C,C,E',F$%%,,-AB'+F$ "G+335F X!%!&%%k2 $y0FM5  	G	s   D DDresultsc                    t        |       }t        d | D              }t        d | D              }t        d | D              }t        d | D              }t        d | D              }t        d | D              }t        d | D              }t        d | D              }	d	t        d
t        dt        fd}
t	                t	        d       t	        d| d| d| d|        t	        d| d| d |
||       d       t	        d| d| d |
||       d       t	        d| d| d |
||       d       t	        d| d| d |
||       d       t	        d|	 d| d |
|	|       d       y )Nc              3   @   K   | ]  }|j                   d k(  sd  yw)rG   r   NrH   .0rs     r   	<genexpr>z print_summary.<locals>.<genexpr>        ?1199+>Q?   c              3   @   K   | ]  }|j                   d k(  sd  yw)rF   r   Nrh   ri   s     r   rl   z print_summary.<locals>.<genexpr>   rm   rn   c              3   @   K   | ]  }|j                   d k(  sd  yw)rE   r   Nrh   ri   s     r   rl   z print_summary.<locals>.<genexpr>   rm   rn   c              3   :   K   | ]  }|j                   sd   ywr   N)r;   ri   s     r   rl   z print_summary.<locals>.<genexpr>   s     <QQ^^q<   c              3   T   K   | ]   }|j                   s|j                  sd  " ywrr   )r;   r<   ri   s     r   rl   z print_summary.<locals>.<genexpr>   s     PA<O<O1Ps   (((c              3   :   K   | ]  }|j                   sd   ywrr   )r>   ri   s     r   rl   z print_summary.<locals>.<genexpr>   s     6!!++A6rs   c              3   :   K   | ]  }|j                   sd   ywrr   )r?   ri   s     r   rl   z print_summary.<locals>.<genexpr>   s     >AA,=,=a>rs   c              3   :   K   | ]  }|j                   sd   ywrr   )rA   ri   s     r   rl   z print_summary.<locals>.<genexpr>   s     6!6rs   numdenr   c                 &    |dk(  ry| |z  dz  ddS )Nr   z0.0%d   z.1f%rT   )rx   ry   s     r   pctzprint_summary.<locals>.pct   s$    !8)c/#&a((r   u#   === 스킬 품질 검증 요약 ===u   전체: u   개 | PASS: z	 | WARN: z	 | FAIL: u   SKILL.md 보유율: /z (rK   u   Frontmatter 유효율: u   evals/ 보유율: u   Registry 동기화율: u   Eval-axes 동기화율: )lensumintrR   print)re   total
pass_count
warn_count
fail_countr;   valid_fmr>   registry_okaxes_okr}   s              r   print_summaryr      s   LE???J???J???J<'<<LPgPPH6w66I>>>K6W66G) )3 )3 )
 
G	
/0	HUG<
|9ZL	R\Q]
^_	 awb\59Q8RRS
TU	#H:Q|nBs8\?Z>[[\
]^	yk5'C	54I3J!
LM	#K=%3{E;R:SST
UV	$WIQugRGU8K7LA
NOr   c                  J    t        d t        j                         D              S )u<   shared/ 제외한 스킬 디렉토리 목록 반환 (정렬)c              3   ^   K   | ]%  }|j                         r|j                  d k7  r| ' yw)r   N)r`   r9   )rj   ds     r   rl   z%collect_skill_dirs.<locals>.<genexpr>   s,      88:!&&H, 	
s   +-)sorted
SKILLS_DIRiterdirrT   r   r   collect_skill_dirsr      s%     %%'  r   c                     t        j                  dt         j                  d      } | j                  ddd       | j                  dd	d
       | j	                         }t        t              }t        t              }t               }|j                  rFt        |j                  z  }|j                         st        d| t        j                         y|g}n
t               }g }|D ]>  }|j                   }	|j#                  |	       t%        |	|||      }
|j'                  |
       @ g }|j                  sht)        |j+                               D ]L  }||vst-        |      }d|_        d|_        |j2                  j'                  d       |j'                  |       N |j4                  s@|D ]  }t        |j7                                 |D ]  }t        d|j                    d        t9        |       |rC|j4                  s7t        dt;        |       d       |D ]  }t        d|j                            t=        d |D              }|rdS dS )Nu!   스킬 품질 검증 스크립트u   
예시:
  python3 skill-quality-check.py                   # 전체 상세 결과
  python3 skill-quality-check.py --summary          # 요약만 출력
  python3 skill-quality-check.py --skill ad-creative  # 특정 스킬만 검증
)r[   formatter_classepilogz	--summary
store_trueu.   요약만 출력 (개별 스킬 결과 생략))actionhelpz--skill
SKILL_NAMEu   특정 스킬만 검증)metavarr   u;   오류: 스킬 디렉토리를 찾을 수 없습니다 — )filer   Fu   유령 등록z[WARN] u9    — registry ✗ (유령 등록 — 디렉토리 없음)uC   
※ 유령 등록 (registry에는 있지만 디렉토리 없음): u   개z   - c              3   :   K   | ]  }|j                   d k(    yw)rE   Nrh   ri   s     r   rl   zmain.<locals>.<genexpr>O  s     81199&8s   r   )argparseArgumentParserRawDescriptionHelpFormatteradd_argument
parse_argsr6   REGISTRY_PATHEVAL_AXES_PATHsetskillr   r`   r   sysstderrr   r9   addrd   r    r   keysr8   r;   r?   r@   summaryrN   r   r   any)parserargsrW   rX   existing_skill_names
target_dir
skill_dirsre   rV   rU   r   ghost_resultsreg_nameghostrk   ghas_fails                    r   mainr     sN   $$7 <<	F =  
 &  
 D 'H.)I &)U zz$**,
  "OPZ|\cfcmcmn \
')
!#G 	^^
  ,ZHiHv	 (*M::x}}/ 	,H33#H-%*"(-%%%,,_=$$U+	, << 	#A!--/"	# 	_AGAFF8#\]^	_ 'T\\TUXYfUgThhklm 	$AE!&&"#	$ 888H1ar   __main__)__doc__r   r1   r   pathlibr   r   r   r   rR   dictr*   r6   r8   rd   listr   r   r   r   rO   exitrT   r   r   <module>r      s  (   
 ./
X%(==h&)997C 7D4K 7|D T 8B 8Bv*** * 	*
 *bP4, P P>DJ O c O d zCHHTV r   