
    (<i1              	          d Z ddlZddlZddlZddlmZ dZdZdede	fdZ
d	e	d
ede	fdZdedefdZdedee   fdZd	e	dede	fdZd	e	d
ede	fdZd-d	e	dedz  de	fdZd-ded
ededz  de	fdZedk(  r ej*                  d      Zej/                  ddd       ej/                  deg ddd        ej/                  d!dd"#       ej1                         Z	  eej4                  ej6                  ej8                  $      Z e ej>                  ed%d&'             yy# e $ rNZ!ddl"Z" e ej>                  d( ee!      id%)      e"jF                  *        e"jH                  d+       Y dZ![!ydZ![!we%$ rKZ!ddl"Z" e ej>                  d(d,e! id%)      e"jF                  *        e"jH                  d+       Y dZ![!ydZ![!ww xY w).u   
meeting-audit.py
미팅 기록 파일을 자동 파싱하여 SKILL.md 규칙 준수 여부를 검증하는 standalone 스크립트.
작성자: 카르티케야 (개발4팀 백엔드)
    N)PathzC/home/jay/workspace/skills/agent-meeting/references/persona-list.mdz /home/jay/workspace/memory/3docsfilepathreturnc                    t        |       }|j                         st        d|        |j                  d      }|j	                         sdg dd|dS t        j                  d|      }|rt        |j                  d            nd}t        j                  d	|      }|r]|j                  d      j	                         }|j                  d
      D cg c]#  }|j	                         s|j	                         % }}ng }t        j                  d|      }	|	r|	j                  d      j	                         nd}
t        j                  d|      }|r|j                  d      j	                         nd}|||
||dS c c}w )u   미팅 파일을 파싱하여 메타데이터를 반환

    returns: {"total_cycles": int, "personas": list[str], "mode": str, "depth": str, "content": str}
    u*   미팅 파일을 찾을 수 없습니다: utf-8encodingr    )total_cyclespersonasmodedepthcontentu%   \*\*총 사이클 수\*\*\s*:\s*(\d+)   u&   \*\*참여 페르소나\*\*\s*:\s*(.+),u    \*\*미팅 모드\*\*\s*:\s*(.+)u    \*\*토론 깊이\*\*\s*:\s*(.+))
r   existsFileNotFoundError	read_textstripresearchintgroupsplit)r   pathr   cycles_matchr   personas_matchraw_personaspr   
mode_matchr   depth_matchr   s                F/home/jay/workspace/.worktrees/task-2057-dev2/scripts/meeting-audit.pyparse_meeting_filer#      sh   
 >D;;="LXJ WXXnngn.G==?
 	
 99EwOL1=3|))!,-1L YYH'RN%++A.4462>2D2DS2IWQQWWYqwwyWW >HJ*4:A$$&"D ))?IK,7Ka &&(RE %  Xs   E9(E9parsedlevelc           
          ddddd}|j                  |d      }| j                  dd      }|dk(  rd||dd	S ||k\  rd||d
| d| d	S d||d| d| d| dd	S )u   사이클 수 vs 레벨 기대값 검증

    returns: {"status": "PASS"|"WARN"|"FAIL", "expected_min": int, "actual": int, "message": str}
    r   r         r   r'   r(      r   PASSu0   Lv.1은 사이클 수 체크를 건너뜁니다.)statusexpected_minactualmessageu   사이클 수 충족: actual=z >= expected_min=FAILu   사이클 수 부족: actual=z < expected_min=z (Lv.u    기준))get)r$   r%   expected_min_mapr-   r.   s        r"   check_cycle_countr3   K   s    
 qQ/#''q1LZZ*Fz(I	
 	
 (6vh>OP\~^	
 	
 (6vh>N|n\abgahhpq	
 	
    persona_strc                     t        j                  d| j                               }|r|j                  d      S | j                         S )u~   페르소나 문자열에서 한글명을 추출.
    예: "토르 (Thor)" → "토르", "엔키(백엔드)" → "엔키"
    u   ([가-힣]+)r   )r   matchr   r   )r5   r7   s     r"   _extract_korean_namer8   q   s=    
 HH_k&7&7&9:E{{1~r4   persona_list_pathc                    t        |       }|j                         sg S |j                  d      }g }|j                         D ]  }|j	                         }|j                  d      s%t        j                  d|      r<|j                  d      D cg c]#  }|j	                         s|j	                         % }}|s||d   }|dk(  rt        |      }|s|j                  |        |S c c}w )u;   persona-list.md에서 등록된 한글명 목록을 파싱.r   r   |z
\|[-| ]+\|r   u   페르소나)r   r   r   
splitlinesr   
startswithr   r7   r   r8   append)	r9   r   r   
registeredlineccells
first_cellkoreans	            r"   _parse_registered_personasrE   |   s    !"D;;=	nngn.GJ ""$ &zz|s#88M4($(JJsOAqqwwyAA1X
'%j1f%!&$  Bs   C,'C,c                     t        |      }| j                  dg       }g }g }|D ]4  }t        |      }||v r|j                  |       $|j                  |       6 t	        d |D              }|sd}	n|rd}	nd}	|	|||dS )u   참여 페르소나 vs 등록 목록 교차 확인

    returns: {"status": "PASS"|"WARN"|"FAIL", "registered": list, "unregistered": list, "loki_present": bool}
    r   c              3   $   K   | ]  }d |v  
 yw)u   로키N ).0r   s     r"   	<genexpr>z+check_persona_validation.<locals>.<genexpr>   s     7x1}7s   r0   WARNr+   )r,   r?   unregisteredloki_present)rE   r1   r8   r>   any)
r$   r9   registered_poolr   r?   rL   personarD   rM   r,   s
             r"   check_persona_validationrQ      s    
 11BCO **Z4HJ L (%g._$f%'( 7h77L	  $$	 r4   c                    | j                  dd      }t        j                  dt        j                  t        j                  z        }t        j                  dt        j                        }|j                  |      }|j                  |      D cg c]  }|j                  |      r| }}t        |      t        |      z   }t        t        j                  d|            }	t        t        j                  d|            }
t        t        j                  d|            }|	xr |
xr |}t        t        j                  d|            }t        t        j                  d	|            }|d
k  rd}n|dk(  rd}n|sd}nd}|||||dS c c}w )u   Devil's Advocate 수행 여부 검증

    returns: {"status": "PASS"|"WARN"|"FAIL", "da_sections_found": int,
              "three_questions": bool, "rebuttal_found": bool, "verdict_found": bool}
    r   r
   z#^#{1,6}\s+.*Devil'?s?\s+Advocate.*$z'^#{1,6}\s+.*\bDA\b\s*(?:\([^)]*\))?\s*$u   실패u   후회u   단순한 대안|더 단순u   반박u   판정r'   r+   r   r0   rK   )r,   da_sections_foundthree_questionsrebuttal_foundverdict_found)	r1   r   compile	MULTILINE
IGNORECASEfindallr   lenbool)r$   r%   r   da_header_patternda_standalone_pattern
da_matchesmda_standalone_matchesrS   has_failure
has_regrethas_simple_altrT   rU   rV   r,   s                   r"   check_dare      sn    ::i,G
 

.
r}}$
 JJ2
 #**73J(=(E(Eg(Nr1VgVnVnopVqQrrJ#.C*DD ryyG45Kbii	734J"))$BGLMN!CjC^O"))Iw78N9g67M z !F FF .*(& 1 ss   F'Ftask_idc                 
   | j                  dd      }t        t        j                  d|            }t        t        j                  d|            xr@ t        t        j                  d|            xr t        t        j                  d|            }|xs |}d}|\t	        t
              |z  }|j                         r8|j                         r(t        |j                               }t        |      dkD  }nd	}|rd
nd}	|	||dS )u   3문서 연결 여부 검증

    returns: {"status": "PASS"|"WARN"|"FAIL", "mentioned": bool, "files_exist": bool | None}
    r   r
   u   3문서 반영u	   계획서u   맥락노트u   체크리스트Nr   Fr+   rK   )r,   	mentionedfiles_exist)r1   r\   r   r   r   DEFAULT_3DOCS_BASEr   is_dirlistiterdirr[   )
r$   rf   r   has_three_docs_phrasehas_all_keywordsrh   ri   docs_dirfilesr,   s
             r"   check_three_docsrr      s    
 ::i,G !+<g!FGRYY|W-. 	9?G45	9-w78 
 &9)9I  $K*+g5??!2))+,Ee*q.KK VfF " r4   meeting_filec           	         t        |       }t        ||      }t        |t              }t	        ||      }t        ||      }||||d}|j                         D 	cg c]  }	|	d   	 }
}	|
j                  d      }|
j                  d      }|
j                  d      }|dkD  rd}n
|dkD  rd}nd}| d| d	| d
}| |||||||d}|S c c}	w )u   전체 감사 실행

    returns: {"meeting_file": str, "level": int, "checks": {...4개 체크 결과...},
              "overall": "PASS"|"WARN"|"FAIL", "summary": str}
    rf   )cycle_countpersona_validationda_check
three_docsr,   r+   rK   r0   r   z	/4 PASS, z WARN, z FAIL)rs   r%   rv   rw   rx   ry   overallsummary)r#   r3   rQ   DEFAULT_PERSONA_LISTre   rr   valuescount)rs   r%   rf   r$   rv   rw   rx   ry   checksrA   statuses
pass_count
warn_count
fail_countrz   r{   results                    r"   	run_auditr   (  s      -F#FE2K1&:NO&H!&':J #0 	F &,]]_5(5H5'J'J'JA~	aIj\EJG %"0 	F M1 6s   C__main__uV   미팅 기록 파일을 파싱하여 SKILL.md 규칙 준수 여부를 검증합니다.)descriptionz--meeting-fileTu+   검증할 미팅 마크다운 파일 경로)requiredhelpz--levelr)   u   미팅 레벨 (1-4))typechoicesr   r   z	--task-idu5   3문서 경로 검증을 위한 태스크 ID (선택))defaultr   ru   Fr'   )ensure_asciiindenterror)r   )filer   u   감사 실행 중 오류: )N)&__doc__argparsejsonr   pathlibr   r|   rj   strdictr#   r   r3   r8   rl   rE   rQ   re   rr   r   __name__ArgumentParserparseradd_argument
parse_argsargsrs   r%   rf   r   printdumpsr   esysstderrexit	ExceptionrH   r4   r"   <module>r      sV     	 \ 7 . . .l
d 
3 
4 
Lc c # $s) @!T !c !d !R3T 3# 3$ 3v T  C$J  $  P,C , ,cDj ,D ,f z$X$$  2J  KF
:  
 "   D   D4,,djj$,,OjdjjeA>?1 2  jdjj'3q6*?cjjQ jdjj'%?s#CDSXY`c`j`jk	s'   AD G $AE--G 5AF;;G 