
    LiE                     L   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deeee
f   z  deeef   fdZ 	 d7dedeeeee
f   z     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eee
f   z     dedefdZ#d8dedz  defdZ$deee
f   dededdfdZ%	 	 d9dedeeeee
f   z     dedz  dedz  deee
f   f
dZ&e'd k(  rCddl(Z( ejR                  ejT                  d!"        e(jV                  d#$      Z,e,j[                  d%d&       e,j[                  d'd&       e,j[                  d(d)g *       e,j[                  d+d,ddd-.       e,j]                         Z/e/j`                  Z0e0Ge/jb                  r;e/jd                  xs d/Z3ej                  j                  e3d0d1e/jb                   d2      Z0e0e,ji                  d3        e&e0e/jj                  e/jd                  e/jb                  4      Z6 e7 ejp                  e6d
d56             yy# e$ r eZd
ZY w xY w):u2  
codex_gate_check.py - Codex G1 설계 게이트 검증 스크립트

Codex CLI를 통해 설계 문서와 영향받는 코드를 리뷰하고,
발견된 리스크 및 개선 제안을 JSON 형식으로 반환합니다.
Codex 장애 시 마아트 폴백(규칙 기반 검증)으로 자동 전환합니다.
    N)Anyz..textreturnc                 
    | g fS N )r   s    //home/jay/workspace/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itemc                 X    t        | t              r| d   | j                  dd      fS | dfS )u<   affected_files 항목을 (path, is_new) 튜플로 정규화.r   is_newF)
isinstancedictget)r+   s    r	   _normalize_affected_itemr1   J   s0    $F|TXXh666;r   	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 ]  }t        |      \  }}	t        j                  j                  |      r|nt        j                  j                  ||      }
t        j                  j	                  |
      rr|	r|j                  dd| 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)가 비어 있습니다: infou"   신규 파일 (아직 미생성): highuM   영향받는 파일이 존재하지 않습니다 (오타 또는 삭제됨?):    u   변경 범위가 큽니다 (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r8   r7   Nr   .0r   s     r	   	<genexpr>z'_maat_fallback_check.<locals>.<genexpr>   s     Bqq}
2Bs   uA   마아트 폴백 검증 통과: 모든 파일이 존재합니다.maat_fallbackNpassriskssuggestionssourcer5   error)r   r   osr   isfileappendr   r#   r1   isabsjoinlen_get_callers_contextsplitr    r!   intr"   any)r2   r3   r4   r5   rJ   rK   contentr+   	file_pathr-   resolvedcallers_ctxlinematchdanger_keywordskwfoundhas_criticals                     r	   _maat_fallback_checkrb   Q   s    NN67"$EK 77>>)$&!XYbXcd	
 "),}}LL *%VW`Va#b  4T:	6 "i 89bggll>[d>eww~~h'$*)KI;'W $*)v  xA  wB  (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   	J)J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)rN   r   rO   CODEX_COMPANION_PATHr   r   tempfileNamedTemporaryFilewritename
subprocessrunenvironcopy
returncodestderrunlinkr*   stdoutr0   TimeoutExpiredr   )rc   r4   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        |      \  }}	 t        j                  d|d|d|dgd	d	d
|      }|j                  dk7  r-t        j                  d||j                  |j                         o	 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}	~	7d}	~	ww xY w# t        j$                  $ r t        j                  d|       Y kt&        $ 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--filesrk   T   )rm   r   rn   ro   r   u>   AST 스크립트 비정상 종료 (file=%s, returncode=%d): %su1   AST 스크립트 JSON 파싱 실패 (file=%s): %sNblast_radiuscallersr<   rA   z- z: u   곳에서 호출됨: u3   AST 스크립트 타임아웃 (30s 초과, file=%s)u7   AST 스크립트 호출 중 예외 발생 (file=%s): %su   함수 호출자 정보:
r=   )rN   r   rR   rO   r   r   r1   rx   ry   r|   r}   r$   r%   r   r&   r0   rP   rS   r   r   )r3   r4   
ast_scriptlinesr+   rY   _r   datar   r   r   top_callers
caller_strs                 r	   rT   rT      s    ni9PQJ77>>*%BJOE .d/5	1,	d^^"  $"F    A%T%%MM	 zz&--0
  88NB7L!-!1!1)R!@G%bqk!YY{3
r)Bs7|n<QR\Q]^_S.d` '$))E*:::+ '' RT]_`a (( 	]NNPR[\ 	dNNTV_abcc	dsJ   1AFE&.AF&F9FFFF)G4
G4G//G4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)rN   r   rO   r   r    r!   r"   r#   lowerisdirr   r:   r   )r2   PROJECT_PATH_MAPDEFAULT_WORKSPACErX   r]   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   	timestampre   r   r   F   ensure_asciiindentNu#   Codex gate 결과 파일 생성: %su*   Codex gate 결과 파일 생성 실패: %s)r   r   rN   r   rR   nowutc	isoformatr   r$   dumpr   r:   r   r   )	r   r   r4   r   r   	gate_file	gate_datar   r   s	            r	   _save_gate_filer   H  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 ]s  }t        |      \  }}t        j                  j                  |      r|nt        j                  j                  ||      }	t        |	      }
|j                  d| d|
        u |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   

영향받는 코드:
r=   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)r5   rJ   rK   c              3   D   K   | ]  }|j                  d       dk(    ywrC   )r0   rD   s     r	   rF   z#codex_gate_check.<locals>.<genexpr>  s     F1quuZ(J6Fs    u6   Codex 리뷰 완료 (source=%s): risks=%d, critical=%srH   )r   r.   strr   r:   r   r   r1   rN   r   rQ   rR   rP   rT   _SANITIZE_AVAILABLE_sanitize_textrS   r   r   rb   r   r0   rW   )r2   r3   r4   r   task_content
code_partsr+   rY   r   rZ   rX   code_contentr[   callers_sectionrc   rL   r   r5   _pii_detectionsr   r   rJ   rK   ra   s                           r	   r   r   V  s   $ /	:nc***
KKU	 #9-LI9U J =/5	1 "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   /I 	I1I,,I1__main__z1%(asctime)s [%(levelname)s] %(name)s: %(message)s)levelformatu    Codex G1 설계 게이트 검증)r9   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)9__doc__r$   loggingrN   r    rx   sys_sysrt   typingr   r   insertrR   dirname__file__r   tuplelistr
   utils.sanitize_gater   r   r   ImportError	getLoggerr   rs   r   r/   r*   boolr1   rb   r   rT   r   r   r   __name__argparsebasicConfigINFOArgumentParserparseradd_argument
parse_argsargsr2   r   r4   wsrM   r3   r   printdumpsr   r   r	   <module>r      s     	 	     		  BGGLL!:DA Bc eCI&6  C
 
		-	.m # # c dTk 43c3h#7 E#t)<L  %	eetCH~-.e e 	e
 
#s(^eP(# (#c (#dTk (#VH;cDcN.B)C H;UX H;]` H;VcDj C 2HDcN HS H# HRV H" "&	ootCH~-.o $Jo 4Z	o
 
#s(^od 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 W   (N s   J 	J#"J#