
    iJM                        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 	 	 d;dedeeeee
f   z     dedededz  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#d<dedz  defdZ$deee
f   dededdfdZ%	 	 	 d=dedeeeee
f   z     dedz  dedz  dedz  deee
f   fd Z&e'd!k(  rbd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[                  d0dd12       e,j]                         Z/e/j`                  Z0e0Ge/jb                  r;e/jd                  xs d3Z3ej                  j                  e3d4d5e/jb                   d6      Z0e0e,ji                  d7        e&e0e/jj                  e/jd                  e/jb                  e/jl                  8      Z7 e8 ejr                  e7d
d9:             yy# e$ r eZd
ZY Cw xY w)>u2  
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-2374-dev7/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_reason
target_dirc           	      (   t         j                  d       ||n|}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dS c c}w )u   
    마아트 독립 검증 폴백.
    규칙 기반으로 파일 존재 여부를 확인하고 결과를 반환합니다.
    u!   Codex 장애 → 마아트 폴백N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r9   r8   Nr   .0r   s     r	   	<genexpr>z'_maat_fallback_check.<locals>.<genexpr>   s     Bqq}
2Bs   uA   마아트 폴백 검증 통과: 모든 파일이 존재합니다.maat_fallbackpassriskssuggestionssourcer5   errorr6   target_dir_source)r   r   osr   isfileappendr   r#   r1   isabsjoinlen_get_callers_contextsplitr    r!   intr"   any)r2   r3   r4   r5   r6   effective_dirrK   rL   contentr+   	file_pathr-   resolvedcallers_ctxlinematchdanger_keywordskwfoundhas_criticals                       r	   _maat_fallback_checkre   Q   s    NN67 #-"8JnM"$EK 77>>)$&!XYbXcd	
 "),}}LL *%VW`Va#b  4T:	6 "i 89bggll=Zc>d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)rP   r   rQ   CODEX_COMPANION_PATHr   r   tempfileNamedTemporaryFilewritename
subprocessrunenvironcopy
returncodestderrunlinkr*   stdoutr0   TimeoutExpiredr   )rf   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--filesrn   T   )rp   r   rq   rr   r   u>   AST 스크립트 비정상 종료 (file=%s, returncode=%d): %su1   AST 스크립트 JSON 파싱 실패 (file=%s): %sNblast_radiuscallersr=   rB   z- z: u   곳에서 호출됨: u3   AST 스크립트 타임아웃 (30s 초과, file=%s)u7   AST 스크립트 호출 중 예외 발생 (file=%s): %su   함수 호출자 정보:
r>   )rP   r   rT   rQ   r   r   r1   r{   r|   r   r   r$   r%   r   r&   r0   rR   rU   r   r   )r3   r4   
ast_scriptlinesr+   r\   _r   datar   r   r   top_callers
caller_strs                 r	   rV   rV      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)rP   r   rQ   r   r    r!   r"   r#   lowerisdirr   r;   r   )r2   PROJECT_PATH_MAPDEFAULT_WORKSPACEr[   r`   project_namedetecteds          r	   _detect_workspace_rootr   5  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   	timestamprh   r   r   F   ensure_asciiindentNu#   Codex gate 결과 파일 생성: %su*   Codex gate 결과 파일 생성 실패: %s)r   r   rP   r   rT   nowutc	isoformatr   r$   dumpr   r;   r   r   )	r   r   r4   r   r   	gate_file	gate_datar   r   s	            r	   _save_gate_filer   N  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| ||       d}|]t
        j                  j                  d      }|r$t
        j                  j                  |      r|}d}n	 ddl
m}  ||      \  }}	|r|}|	}||}d	}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       t1        ||      }|d}	t        j	                  d       nd}|@t        j	                  d|       t3        | |||xs d|      }||d<   |rt5        |||       |S |j                  d g       }|j                  d!g       }t7        d" |D              }t        j	                  d#|	t-        |      |       | |||	dd||d$}|rt5        |||       |S # t        $ r t        j                  d       Y Uw xY w# 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)
        target_dir: affected_files를 읽을 디렉토리 (worktree 등). 미지정 시 task_id로 자동 탐지, 환경변수 CODEX_TARGET_DIR도 인식.

    Returns:
        검증 결과 dict (pass, risks, suggestions, source, error, target_dir, target_dir_source)
    NuK   codex_gate_check 시작: task_file=%s, affected_files=%s, workspace_root=%sparamCODEX_TARGET_DIRrs   r   )resolve_worktree_target_diru   worktree_resolver import 실패workspace_root_fallbackztarget_dir=%s (source=%s)u0   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   r6   rO   rK   rL   c              3   D   K   | ]  }|j                  d       dk(    ywrD   )r0   rE   s     r	   rG   z#codex_gate_check.<locals>.<genexpr>  s     F1quuZ(J6Fs    u6   Codex 리뷰 완료 (source=%s): risks=%d, critical=%srI   )r   r.   strr   r;   rP   r}   r0   r   r   utils.worktree_resolverr   ImportErrorr   r   r1   rS   rT   rR   rV   _SANITIZE_AVAILABLE_sanitize_textrU   r   r   re   r   rY   )r2   r3   r4   r   r6   rO   
env_targetr   r]   rM   task_content
code_partsr+   r\   r   r[   code_contentr^   callers_sectionrf   r   r5   _pii_detectionsr   r   rK   rL   rd   s                               r	   r   r   \  s]   ( /	:nc***
KKU	  ZZ^^$67
"''--
3#J %BO#>w#G &!)J(.% #
5
KK+Z9JK #9-LI9U J =/5	1 "i 89bggll:W`>a!(+D6';<	=
 /96;;z*>\L '~~FK /:[M*rO     
F FFO 	n&4V&<#FO@#oBVW 	hi KK23!&*5F",-r ~NP_`%~~GcZc!
 '8"#FG^< JJw#E**]B/KFFFL
KKH&RUV[R\^jk ! " .	F 8M}  B@ABb  	nNNiklmm	ns*   K /K2 K/.K/2	L;LL__main__z1%(asctime)s [%(levelname)s] %(name)s: %(message)s)levelformatu    Codex G1 설계 게이트 검증)r:   z	--task-id)defaultz--task-filez--affected-files*)nargsr   z--workspace-rootz--workspaceum   워크스페이스 루트 경로 (미지정 시 task 파일에서 자동 감지, 폴백: /home/jay/workspace))destr   helpz--target-diru   affected_files를 읽을 디렉토리 (worktree 등). 미지정 시 task_id로 자동 탐지, 환경변수 CODEX_TARGET_DIR도 인식.)r   r   r   r   tasksz.mdu;   --task-file 또는 --task-id 중 하나가 필요합니다.)r   r6   r   r   )r   Nr   )NNN):__doc__r$   loggingrP   r    r{   sys_sysrw   typingr   r   insertrT   dirname__file__r   tuplelistr
   utils.sanitize_gater   r   r   r   	getLoggerr   rv   r   r/   r*   boolr1   re   r   rV   r   r   r   __name__argparsebasicConfigINFOArgumentParserparseradd_argument
parse_argsargsr2   r   r4   wsrN   r3   r6   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  %!kktCH~-.k k 	k
 d
k 
#s(^k\(# (#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" "&!LLtCH~-.L $JL 4Z	L
 d
L 
#s(^L^ zGgll3fg$X$$1STF
T2
t4
*#rB
|    V  
 D IT\\  9$9GGLLXw4<<.8LM	RSi)<)<d>Q>Q[_[g[gtx  uD  uD  EF	*$**V%
:;A ]   (N s   K 	KK