
    (<i'                       U d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	 ddl
mZmZmZmZmZ e G d d             Ze G d	 d
             ZdIdZdJdZdKdZdLdZ G d de      Z eh d      Zded<   i dg ddg ddg ddg ddg ddg dd g d!d"g d#d$g d%d&g d'd(g d)d*g d+d,g d-d.g d/d0g d1d2g d3d4g d5g d6g d7g d8d9Zd:ed;<   d<Zd=ed><   d?ad@edA<   dMdBZdNdCZdOdDZdPdEZ dQdFZ!dRdGZ"yH)Suu  스킬 3계층 Progressive Disclosure 로더.

SKILL.md 기반 스킬을 3단계로 로드한다:
  1. list  → 이름 + 1줄 설명 (SkillSummary)
  2. view  → 설명 + 트리거 + 의존성 (SkillDetail)
  3. load  → SKILL.md 전체 내용 (str)

SKILL.md 포맷:
    ---                                   ← YAML frontmatter (선택)
    name: skill-name
    description: 1줄 설명
    triggers:
      - "trigger1"
    requires:
      - "dependency"
    category: general
    ---

    # Skill Title                         ← 첫 번째 헤딩 (frontmatter 없을 때 설명으로 사용)

    본문 내용...

Usage:
    from utils.skill_loader import list_skills, view_skill, load_skill
    summaries = list_skills("/home/jay/workspace/skills")
    detail = view_skill("/home/jay/workspace/skills", "retro")
    content = load_skill("/home/jay/workspace/skills", "pdf")
    )annotations)	dataclassfield)Enum)Path)extract_categoryextract_descriptionextract_requiresextract_triggersparse_frontmatterc                  4    e Zd ZU dZded<   ded<   dZded<   y)SkillSummaryu8   스킬 1계층: 이름 + 1줄 설명 (목록 표시용).strnamedescriptiongeneralcategoryN)__name__
__module____qualname____doc____annotations__r        C/home/jay/workspace/.worktrees/task-2057-dev2/utils/skill_loader.pyr   r   -   s    B
IHcr   r   c                  l    e Zd ZU dZded<   ded<    ee      Zded<    ee      Zded<   d	Z	ded
<   y)SkillDetailu<   스킬 2계층: 설명 + 트리거 + 의존성 (상세 뷰).r   r   r   )default_factory	list[str]triggersrequires 	full_pathN)
r   r   r   r   r   r   listr    r!   r#   r   r   r   r   r   6   s8    F
I5Hi55Hi5Isr   r   c                    | |z  dz  S )u4   스킬 이름으로 SKILL.md 경로를 반환한다.SKILL.mdr   )
skills_dirr   s     r   _skill_md_pathr(   A   s    z))r   c                   t        |       }|j                         r|j                         sg S g }t        |j	                               D ]  }|j                         s|dz  }|j                         s*	 |j                  d      }t        |      \  }}|j                  d      xs |j                  }t        ||      }	t        |||j                        }
|j                  t        t        |      |	|
              |S # t        $ r Y w xY w)u  스킬 디렉토리에서 모든 스킬의 요약을 반환한다 (1계층).

    SKILL.md 파일이 있는 직접 하위 디렉토리만 스캔한다.

    Args:
        skills_dir: 스킬 디렉토리 경로.

    Returns:
        SkillSummary 목록 (이름 오름차순).
    r&   utf-8encodingr   )r   r   r   )r   existsis_dirsortediterdir	read_textOSErrorr   getr   r	   r   appendr   r   )r'   base	summariesentryskill_mdcontentfmbodyr   r   r   s              r   list_skillsr<   F   s    
D;;=	$&I' 
||~:% 	(('(:G %W-Dvvf~+)"d3#Bejj9Y'!	
#
2 !  		s   4D  	DDc           
        t        |       }t        ||      }|j                         st        d| d|       |j	                  d      }t        |      \  }}|j                  d      xs |}t        ||      }t        ||      }	t        |      }
t        t        |      ||	|
t        |j                                     S )u>  특정 스킬의 상세 정보를 반환한다 (2계층).

    Args:
        skills_dir: 스킬 디렉토리 경로.
        name: 스킬 이름 (디렉토리 이름).

    Returns:
        SkillDetail (설명 + 트리거 + 의존성).

    Raises:
        FileNotFoundError: 스킬이 존재하지 않는 경우.
       스킬 '
   ' 없음: r*   r+   r   )r   r   r    r!   r#   )r   r(   r-   FileNotFoundErrorr1   r   r3   r	   r   r
   r   r   resolve)r'   r   r5   r8   r9   r:   r;   
skill_namer   r    r!   s              r   
view_skillrC   r   s     
DdD)H??(4&
8* EFF  ' 2G )HB'4J%b$/KD)H#H_h&&() r   c                    t        |       }t        ||      }|j                         st        d| d|       |j	                  d      S )u4  특정 스킬의 SKILL.md 전체 내용을 반환한다 (3계층).

    Args:
        skills_dir: 스킬 디렉토리 경로.
        name: 스킬 이름 (디렉토리 이름).

    Returns:
        SKILL.md 전체 텍스트.

    Raises:
        FileNotFoundError: 스킬이 존재하지 않는 경우.
    r>   r?   r*   r+   )r   r(   r-   r@   r1   )r'   r   r5   r8   s       r   
load_skillrE      sP     
DdD)H??(4&
8* EFFw//r   c                      e Zd ZdZdZdZdZy)
SkillLevelu"   스킬 로드 우선순위 레벨.corestandardextendedN)r   r   r   r   CORESTANDARDEXTENDEDr   r   r   rG   rG      s    ,DHHr   rG   >   qc-rulestdd-enforcementnuclear-approvalsystematic-debuggingverification-before-completionzfrozenset[str]SECURITY_WHITELISTzblog-writer)u	   블로그blogu	   포스팅pdf)rU   PDFz.pdfz	seo-audit)seoSEOu   검색엔진zfrontend-design)u   프론트엔드frontendUIu   웹 디자인copywriting)u   카피copyu   카피라이팅z	naver-seo)u	   네이버naverDataLabzfullstack-builder)u	   풀스택	fullstackSaaSu   랜딩zcanvas-design)u	   포스터u   일러스트u	   그래픽docx)wordWordra   z.docxzgemini-image)u   이미지 생성geminiu   포토리얼zwebapp-testing)
playwrightu   브라우저 테스트u   웹 테스트zadvanced-crawling)u	   크롤링u   스크래핑crawlzbook-writer)u   집필u   소설u   원고u
   책 쓰기zcompetitor-analyst)u	   경쟁사
competitoru	   역분석zpricing-strategy)u   가격pricingu   요금zresearch-prompt)u	   리서치u   연구u   논문zstrategy-prompt)u   전략u   90일KPI)u   마케팅 전략u	   캠페인u   콘텐츠 캘린더)u   미팅u   페르소나u   의견 수집)u   회고retrospectiveretro)zmarketing-strategistzagent-meetingrk   zdict[str, list[str]]KEYWORD_TRIGGERS)securityu   보안auditzred-teamztuple[str, ...]_SECURITY_DETECT_KEYWORDSTbool_PROGRESSIVE_DISCLOSURE_ENABLEDc                    | a y)uR   Progressive Disclosure 기능 토글. False이면 모든 스킬을 CORE로 취급.Nrq   )enableds    r   set_progressive_disclosureru      s
     '.#r   c                     t         S )u8   Progressive Disclosure 활성화 여부를 반환한다.rs   r   r   r   !is_progressive_disclosure_enabledrw      s    **r   c                    t         st        j                  S | t        v rt        j                  S | t        v rt        j
                  S t        j                  S )uG   스킬 이름을 CORE / STANDARD / EXTENDED 중 하나로 분류한다.)rq   rG   rK   rS   rl   rL   rM   )r   s    r   classify_skillry      sC    *!!"""r   c                r   | j                         }g }t        j                         D ]1  \  }}|D ]'  }|j                         |v s|j                  |        1 3 |sg S t	        |      }|D ci c]  }|j
                  | }	}g }
|D ]'  }|	j                  |      }||
j                  |       ) |
S c c}w )u_   사용자 프롬프트에서 KEYWORD_TRIGGERS를 매칭해 SkillSummary 목록을 반환한다.)lowerrl   itemsr4   r<   r   r3   )promptr'   prompt_lowermatched_namesrB   keywordskwall_summariessname_to_summaryresultr   summarys                r   match_skills_by_promptr   	  s    <<>L!M 0 6 6 8 
H 	Bxxz\)$$Z0	 	
+M*78Qqvvqy8O8!#F #!%%d+MM'"#
 M 9s   .B4c                p    t        |       D cg c]  }t        |j                        |k(  s| c}S c c}w )uS   주어진 SkillLevel에 해당하는 스킬의 SkillSummary 목록을 반환한다.)r<   ry   r   )r'   levelr   s      r   get_skills_by_levelr   (  s+    ":.R!.2HE2QARRRs   33c                   g }t        |       D ]r  }|j                  t        v r|j                   d|j                   j	                         t        fdt        D              sX|j                  |j                         t |S )uf   보안 관련이지만 화이트리스트에 미등록된 스킬을 감지하여 경고 목록 반환. c              3  &   K   | ]  }|v  
 y w)Nr   ).0r   combineds     r   	<genexpr>z+check_security_whitelist.<locals>.<genexpr>;  s     B"rX~Bs   )r<   r   rS   r   r{   anyro   r4   )r'   warningsr   r   s      @r   check_security_whitelistr   2  sv    Hz* *<<--ll^1W%8%8$9:@@BB(ABBOOGLL)* Or   N)r'   r   r   r   returnr   )r'   
str | Pathr   list[SkillSummary])r'   r   r   r   r   r   )r'   r   r   r   r   r   )rt   rp   r   None)r   rp   )r   r   r   rG   )r}   r   r'   r   r   r   )r'   r   r   rG   r   r   )r'   r   r   r   )#r   
__future__r   dataclassesr   r   enumr   pathlibr   utils.skill_parserr   r	   r
   r   r   r   r   r(   r<   rC   rE   rG   	frozensetrS   r   rl   ro   rq   ru   rw   ry   r   r   r   r   r   r   <module>r      s  : # (         *
)X!H06  &/& N *5*	!* /* M	*
 8* 2* E* ?* -* B* O* ?* ?* B* 7*  8!*" 1#*$ U@1)* & 0. ?  )-  ,.+ >Sr   