
    RiB                        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ZddlZddl	m
Z
 ej                  j                  dej                  j                  ej                  j                  e      d             dedeeef   fdZ	 ddlmZ d	Z ej2                  d      ZdZdedefdZdededz  fdZ	 d5dedee   dededeee
f   f
dZdedededz  fdZ dee   dedefdZ!d6dedz  defdZ"deee
f   dededdfdZ#	 	 d7dedee   dedz  dedz  deee
f   f
dZ$e%dk(  rCddl&Z& ejN                  ejP                  d         e&jR                  d!"      Z*e*jW                  d#d$       e*jW                  d%d$       e*jW                  d&d'g (       e*jW                  d)d*ddd+,       e*jY                         Z-e-j\                  Z.e.Ge-j^                  r;e-j`                  xs d-Z1ej                  j                  e1d.d/e-j^                   d0      Z.e.e*je                  d1        e$e.e-jf                  e-j`                  e-j^                  2      Z4 e5 ejl                  e4d
d34             yy# e$ r eZd
ZY w xY w)8u2  
codex_gate_check.py - Codex G1 설계 게이트 검증 스크립트

Codex CLI를 통해 설계 문서와 영향받는 코드를 리뷰하고,
발견된 리스크 및 개선 제안을 JSON 형식으로 반환합니다.
Codex 장애 시 마아트 폴백(규칙 기반 검증)으로 자동 전환합니다.
    N)Anyz..textreturnc                 
    | g fS N )r   s    I/home/jay/workspace/.worktrees/task-2117-dev1/scripts/codex_gate_check.py_sanitize_text_noopr
      s    8O    )sanitize_textTFcodex_gate_checkzT/home/jay/.claude/plugins/cache/openai-codex/codex/1.0.3/scripts/codex-companion.mjspathc                     	 t        | dd      5 }|j                         cddd       S # 1 sw Y   yxY w# t        $ r!}t        j	                  d| |       Y d}~yd}~ww xY w)uP   파일을 안전하게 읽어 내용을 반환. 실패 시 빈 문자열 반환.rutf-8encodingNu   파일 읽기 실패: %s — %s )openread	Exceptionloggerwarning)r   fes      r	   _read_file_safer   &   sV    $g. 	!668	 	 	 8$Bs(   6 *	6 36 6 	A AA outputc                    t        j                  d|       }|r5|j                  d      j                         }	 t	        j
                  |      S t        j                  d|       }|r5|j                  d      j                         }	 t	        j
                  |      S y# t        j                  $ r Y cw xY w# t        j                  $ r Y yw xY w)u   
    Codex stdout에서 JSON 객체를 추출합니다.
    ```json ... ``` 블록 또는 직접 JSON 형식을 지원합니다.
    z```json\s*([\s\S]+?)\s*```   z\{[\s\S]+\}r   N)researchgroupstripjsonloadsJSONDecodeError)r   code_block_match	candidatebrace_matchs       r	   _extract_json_from_outputr*   0   s     yy!>G$**1-335		::i((
 ))NF3K%%a(..0		::i((  ## 		 ## 		s#   B B5 B21B25C
C	task_fileaffected_filesworkspace_rootfallback_reasonc                    t         j                  d       g }g }t        j                  j	                  |       s|j                  dd|  d       n2t        |       }|j                         s|j                  dd|  d       |D ]z  }t        j                  j                  |      r|nt        j                  j                  ||      }t        j                  j	                  |      rd|j                  dd| d       | t        |      dkD  r!|j                  dd	t        |       d
d       t        ||      }	|	r|	j                  d      D ]^  }
t        j                  d|
      }|st        |j!                  d            dk\  s:|j                  dd|
j                          d       ` |j                  d|	        t        j                  j	                  |       rLt        |       }g d}|D cg c]	  }||v s| }}|r'|j                  dddj                  |       dd       t#        d |D              }|s|j                  d       | ||d|ddS c c}w )u   
    마아트 독립 검증 폴백.
    규칙 기반으로 파일 존재 여부를 확인하고 결과를 반환합니다.
    u!   Codex 장애 → 마아트 폴백criticalu7   설계 문서(task_file)가 존재하지 않습니다: )severitydescriptionu1   설계 문서(task_file)가 비어 있습니다: u2   영향받는 파일이 존재하지 않습니다:    highu   변경 범위가 큽니다 (u4   개 파일). 리뷰를 신중하게 진행하세요.
u   (\d+)곳에서 호출됨r   
   u   고영향 파일 감지: u   AST 의존성 분석 결과:
)u   인증u   결제u   보안u   권한PIIu   개인정보u   API키u   토큰mediumu1   설계 문서에 보안 민감 키워드 발견: , u   . 보안 리뷰 권장.c              3   ,   K   | ]  }|d    dk(    ywr1   r0   Nr   .0r   s     r	   	<genexpr>z'_maat_fallback_check.<locals>.<genexpr>   s     Bqq}
2Bs   uA   마아트 폴백 검증 통과: 모든 파일이 존재합니다.maat_fallbackNpassriskssuggestionssourcer.   error)r   r   osr   isfileappendr   r#   isabsjoinlen_get_callers_contextsplitr    r!   intr"   any)r+   r,   r-   r.   rB   rC   content	file_pathresolvedcallers_ctxlinematchdanger_keywordskwfoundhas_criticals                   r	   _maat_fallback_checkrZ   J   so    NN67"$EK 77>>)$&!XYbXcd	
 "),}}LL *%VW`Va#b $ 	 "i 89bggll>[d>eww~~h'LL *%WXaWb#c >Q"!=c.>Q=R  SG   H	
 '~~FK%%d+ 	DII94@EU[[^,2$*)B4::<.'Q	 	;K=IJ 
ww~~i !),m-?w??LL (%VW[W`W`afWgVhh  $A BEBBL^_ ! "!*  @s   7	IIpromptc           	         t         j                  j                  t              st        j                  dt               yd}	 t        j                  dddd      5 }|j                  |        |j                  }ddd       t        j                  dt        d	d
|dgddd|t         j                  j                               }|j                  dk7  rht        j                  d|j                  |j                  dd        	 |r6t         j                  j                  |      rt        j                   |       yyyt#        |j$                        }|rd|v r|j'                  dd      }|sOt        j                  d       	 |r6t         j                  j                  |      rt        j                   |       yyyt#        |      |r6t         j                  j                  |      rt        j                   |       S S S ||r6t         j                  j                  |      rt        j                   |       S S S # 1 sw Y   xY w# t        j(                  $ rP t        j                  d       Y |r6t         j                  j                  |      rt        j                   |       yyyt*        $ rX}t        j                  d|       Y d}~|r6t         j                  j                  |      rt        j                   |       yyyd}~ww xY w# |r6t         j                  j                  |      rt        j                   |       w w w xY w)uK   codex-companion.mjs task 명령으로 Codex 호출. 실패 시 None 반환.z!codex-companion.mjs not found: %sNwz.txtFr   )modesuffixdeleter   nodetaskz--prompt-file--jsonTx   )capture_outputr   timeoutcwdenvr   u2   codex-companion 비정상 종료: rc=%d, stderr=%s   	rawOutputr   u&   codex-companion rawOutput 비어있음u#   codex-companion 타임아웃 (120s)u!   codex-companion 호출 예외: %s)rF   r   rG   CODEX_COMPANION_PATHr   r   tempfileNamedTemporaryFilewritename
subprocessrunenvironcopy
returncodestderrunlinkr*   stdoutgetTimeoutExpiredr   )r[   r-   prompt_filer   resultparsedrawr   s           r	   _run_codex_companionr~      s   77>>./:<PQK"#((c&Y`a 	!efGGFO&&K	! )6?KQYZ

!
 !NNOQWQbQbdjdqdqrvsvdwx$ 277>>+6IIk" 7;! +6==9kV+**["-CGH 277>>+6IIk" 7; -S1 277>>+6IIk" 7;  277>>+6IIk" 7;?	! 	!0 $$ <=
 277>>+6IIk" 7;	  :A>277>>+6IIk" 7;	 277>>+6IIk" 7;sb   I H49BI 9AI 7
I :I 4H>9I (L)L #L+K>L >LL :M c           
         | syt         j                  j                  |dd      }t         j                  j                  |      st        j                  d|       yg }| D ]  }	 t        j                  d|d|d|dgd	d	d
|      }|j                  dk7  r-t        j                  d||j                  |j                         a	 t        j                  |j                        }|j                  di       }|j                  dg       }	|	r9|	dd }
dj                  |
      }|j                  d| dt!        |	       d|         |syddj                  |      z   S # t        j                  $ r"}t        j                  d||       Y d}~)d}~ww xY w# t        j"                  $ r t        j                  d|       Y ]t$        $ r"}t        j                  d||       Y d}~d}~ww xY w)u0  
    AST 스크립트를 이용해 affected_files 각각의 callers 정보를 조회합니다.

    Args:
        affected_files: 영향받는 파일 경로 목록
        workspace_root: 워크스페이스 루트 경로

    Returns:
        callers 정보 문자열 (비어있으면 빈 문자열)
    r   scriptszast_dependency_map.pyu)   AST 스크립트를 찾을 수 없음: %spython3z--rootz--filesrc   T   )re   r   rf   rg   r   u>   AST 스크립트 비정상 종료 (file=%s, returncode=%d): %su1   AST 스크립트 JSON 파싱 실패 (file=%s): %sNblast_radiuscallersr3   r9   z- z: u   곳에서 호출됨: u3   AST 스크립트 타임아웃 (30s 초과, file=%s)u7   AST 스크립트 호출 중 예외 발생 (file=%s): %su   함수 호출자 정보:
r5   )rF   r   rJ   rG   r   r   rp   rq   rt   ru   r$   r%   rw   r&   rx   rH   rK   ry   r   )r,   r-   
ast_scriptlinesrQ   r{   datar   r   r   top_callers
caller_strs               r	   rL   rL      s    ni9PQJ77>>*%BJOE# -d	,	d^^"  $"F    A%T%%MM	 zz&--0
  88NB7L!-!1!1)R!@G%bqk!YY{3
r)Bs7|n<QR\Q]^_Q-d^ '$))E*:::+ '' RT]_`a (( 	]NNPR[\ 	dNNTV_abcc	dsJ   #AFE AFF+FFFF)G&<G&G!!G&c                    ddd}d}| rt         j                  j                  |       rt        |       }t	        j
                  d|      }|r|j                  d      j                         j                         }||v rS||   }t         j                  j                  |      rt        j                  d||       |S t        j                  d|       |S )	uX   task 파일에서 프로젝트를 파싱하여 workspace_root를 자동 감지합니다.z/home/jay/projects/InsuRoz/home/jay/projects/insuwiki)insuroinsuwiki/home/jay/workspaceu    ##\s*프로젝트\s*\n-?\s*(\S+)r   u%   프로젝트 자동 감지: %s → %su8   감지된 프로젝트 경로가 존재하지 않음: %s)rF   r   rG   r   r    r!   r"   r#   lowerisdirr   infor   )r+   PROJECT_PATH_MAPDEFAULT_WORKSPACErP   rU   project_namedetecteds          r	   _detect_workspace_rootr     s     .1 .RWW^^I.!),		=wG ;;q>//1779L//+L977==*KK GW_`#ONN#]_ghr   r{   task_idc                    ddl m }m} t        j                  j	                  |dd| d      }i | ||j                  |j                        j                         d}	 t        |dd	      5 }t        j                  ||d
d       ddd       t        j                  d|       y# 1 sw Y    xY w# t        $ r }t        j                  d|       Y d}~yd}~ww xY w)u/   Codex gate 결과를 파일로 저장합니다.r   )datetimetimezonememoryeventsz.codex-gate)r   	timestampr]   r   r   F   ensure_asciiindentNu#   Codex gate 결과 파일 생성: %su*   Codex gate 결과 파일 생성 실패: %s)r   r   rF   r   rJ   nowutc	isoformatr   r$   dumpr   r   r   r   )	r{   r   r-   r   r   	gate_file	gate_datar   r   s	            r	   _save_gate_filer   7  s    +^XxG9KAXYIc6cgHLL<V<`<`<bcIH)S73 	BqIIiqA	B99E	B 	B  HCQGGHs0   B2 -B&B2 &B/+B2 2	C;CCc                    |t        |       }t        |t              sJ t        j	                  d| ||       t        |       }|st        j                  d|        g }|D ]e  }t        j                  j                  |      r|nt        j                  j                  ||      }t        |      }|j                  d| d|        g |rdj                  |      nd}	t        ||      }
|
rd|
 nd}d	| d
|	 | d}d}d}d}t        r1	 t        |      \  }}|rt        j	                  dt        |             nt        j                  d       t        j	                  d       t#        ||      }|d}t        j	                  d       nd}|:t        j	                  d|       t%        | |||xs d      }|rt'        |||       |S |j)                  dg       }|j)                  dg       }t+        d |D              }t        j	                  d|t        |      |       | |||ddd}|rt'        |||       |S # t         $ r!}t        j                  d|       Y d}~d}~ww xY w)u  
    Codex G1 설계 게이트 검증 메인 함수.

    Args:
        task_file: 설계 문서(task 파일) 경로
        affected_files: 영향받는 파일 경로 목록
        workspace_root: 워크스페이스 루트 경로 (None이면 task 파일에서 자동 감지, 폴백: /home/jay/workspace)
        task_id: task ID (결과 파일 자동 생성에 사용, 예: task-2086)

    Returns:
        검증 결과 dict (pass, risks, suggestions, source, error)
    NuK   codex_gate_check 시작: task_file=%s, affected_files=%s, workspace_root=%su0   task_file 내용 없음 또는 읽기 실패: %sz--- z ---
z

u   (영향받는 파일 없음)r   u   다음 설계 문서와 코드를 리뷰하여 JSON 형식으로 응답하세요.

응답 형식:
{"risks": [{"severity": "critical|high|medium|low", "description": "설명"}], "suggestions": ["제안1"]}

설계 문서:
u   

영향받는 코드:
r5   codexu"   PII 마스킹 완료: %d건 감지uL   sanitize_text 실행 중 예외: %s. 원본 프롬프트를 전달합니다.uO   sanitize_gate 미사용: import 실패. 원본 프롬프트를 전달합니다.u    Codex companion 호출 시도...codex_companionu   codex-companion 성공uV   codex-companion 실행 실패 (returncode!=0, 타임아웃, 또는 JSON 파싱 실패)u8   Codex companion 실패 → 마아트 폴백 (사유: %s)unknown)r.   rB   rC   c              3   D   K   | ]  }|j                  d       dk(    ywr;   )rx   r<   s     r	   r>   z#codex_gate_check.<locals>.<genexpr>  s     F1quuZ(J6Fs    u6   Codex 리뷰 완료 (source=%s): risks=%d, critical=%sr@   )r   
isinstancestrr   r   r   r   rF   r   rI   rJ   rH   rL   _SANITIZE_AVAILABLE_sanitize_textrK   r   r~   rZ   r   rx   rO   )r+   r,   r-   r   task_content
code_partsrQ   rR   rP   code_contentrS   callers_sectionr[   rD   r|   r.   _pii_detectionsr   r{   rB   rC   rY   s                         r	   r   r   E  s   $ /	:nc***
KKU	 #9-LI9U J# =	 "i 89bggll>[d>e!(+D6';<= /96;;z*>\L '~~FK /:[M*rO     
F FFO 	n&4V&<#FO@#oBVW 	hi KK23!&.9F",-r ~NP_`%~~GcZc
 FG^< JJw#E**]B/KFFFL
KKH&RUV[R\^jk ! "F 8MS  	nNNiklmm	ns   	/H9 9	I#II#__main__z1%(asctime)s [%(levelname)s] %(name)s: %(message)s)levelformatu    Codex G1 설계 게이트 검증)r2   z	--task-id)defaultz--task-filez--affected-files*)nargsr   z--workspace-rootz--workspaceum   워크스페이스 루트 경로 (미지정 시 task 파일에서 자동 감지, 폴백: /home/jay/workspace))destr   helpr   r   tasksz.mdu;   --task-file 또는 --task-id 중 하나가 필요합니다.)r   r   r   )r   r   )NN)7__doc__r$   loggingrF   r    rp   sys_sysrl   typingr   r   insertrJ   dirname__file__r   tuplelistr
   utils.sanitize_gater   r   r   ImportError	getLoggerr   rk   r   dictr*   rZ   r~   rL   r   r   r   __name__argparsebasicConfigINFOArgumentParserparseradd_argument
parse_argsargsr+   r   r-   wsrE   r,   r{   printdumpsr   r   r	   <module>r      sK     	 	     		  BGGLL!:DA Bc eCI&6  C
 
		-	.m # # c dTk < %	\\I\ \ 	\
 
#s(^\~(# (#c (#dTk (#VG;c G;C G;C G;TcDj C 2HDcN HS H# HRV H" "&	nnIn $Jn 4Z	n
 
#s(^nb zGgll3fg$X$$1STF
T2
t4
*#rB
|   D IT\\  9$9GGLLXw4<<.8LM	RSi)<)<d>Q>Q[_[g[ghF	*$**V%
:;7 s   (N s   I) )	I65I6