
    [i|                        d 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                  ej                  j                  e	            Z
e
ej                  vrej                  j                  de
       ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z  	 ddlm!Z! 	 ddlm#Z# 	 ddl$m%Z%m&Z& dZ'd
e(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)fdZ-d
e(de)fdZ.d
e(de/e(   fdZ0d
e(de/e(   ddfdZ1d
e(de/ddfdZ2dAdZ3g dZ4h dZ5g dddgdgdgdd gd!Z6d"gZ7dejp                  fd#Z9d$e(de/f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/e(   de/e(   fd-Z@	 	 	 	 dBd.e(d(e/d
e(d/e(d0e/d1e(d2e/d*e(d3e(d4e/dz  d5e>de;fd6ZAdCd7e;d
e(d8e(d9e/dz  ddf
d:ZBd&e;de;fd;ZCd
e(d&e;de;fd<ZDd7e;d=e(ddfd>ZEde)fd?ZFeGd@k(  r ej                   eF              yy# e"$ r dZ!Y ?w xY w# e"$ r dZ#Y Fw xY w# e"$ r
 dZ%dZ&d	Z'Y Mw xY w)Du   
qc_verify.py - post-task 자동 검증 메인 스크립트
불칸(Vulcan) 개발1팀 QC 도구

Usage:
    python3 qc_verify.py --task-id task-xxx [options]
    N)datetime)
api_healthbrowser_verifycritical_gapdata_integrityduplicate_check
file_checkfile_touch_ratio_checkgit_evidencel1_smoketest_checkplanned_checkpyright_checkschema_contractscope_checksignature_checkspec_compliancestyle_checksymbol_existence_check	tdd_checktest_runnerthree_docs_check)	png_check)claude_md_check)create_circuit_breakerRecoveryActionTFtask_id
check_namereturnc                    d}t         j                  j                  ||  d| d      }	 t        |      5 }t	        |j                         j                               cddd       S # 1 sw Y   yxY w# t        t        f$ r Y yw xY w)u   QC 재시도 카운터 읽기../home/jay/workspace/memory/logs/retry-counters.	.qc_countNr   )	ospathjoinopenintreadstripFileNotFoundError
ValueError)r   r   counter_dircounter_filefs        G/home/jay/workspace/.worktrees/task-2520-dev4/teams/shared/qc_verify.py_get_retry_countr0   ?   sw    BK77<<y*Y-OPL, 	)1qvvx~~'(	) 	) 	)z* s.   A2 'A&	A2 &A/+A2 /A2 2BBc                    d}t        j                  |d       t         j                  j                  ||  d| d      }t	        | |      dz   }t        |d      5 }|j                  t        |             ddd       |S # 1 sw Y   |S xY w)	u4   QC 재시도 카운터 증가 후 현재 값 반환.r    Texist_okr!   r"      wN)r#   makedirsr$   r%   r0   r&   writestr)r   r   r,   r-   countr.   s         r/   _increment_retry_countr:   J   s}    BKKKd+77<<y*Y-OPLWj1A5E	lC	  A	E
LLs   B  B
c                     d|  d}	 t        |      5 }t        |j                         j                               cddd       S # 1 sw Y   yxY w# t        t
        f$ r Y yw xY w)u2   태스크 .done 제출 재시도 카운터 읽기."/home/jay/workspace/memory/events/.retry_countNr   )r&   r'   r(   r)   r*   r+   )r   r-   r.   s      r/   _get_task_retry_countr>   U   s_    7yML, 	)1qvvx~~'(	) 	) 	)z* s-   A 'A	A A	A A A"!A"c                    d|  d}t        j                  t         j                  j                  |      d       t	        |       dz   }t        |d      5 }|j                  t        |             ddd       |S # 1 sw Y   |S xY w)uH   태스크 .done 제출 재시도 카운터 증가 후 현재 값 반환.r<   r=   Tr2   r4   r5   N)r#   r6   r$   dirnamer>   r&   r7   r8   )r   r-   r9   r.   s       r/   _increment_task_retry_countrA   _   sp    7yMLKK-=!'*Q.E	lC	  A	E
LLs   A::Bc                    ddl }t        j                  j                  dd      }t        j                  j                  |dd|  d      }	 t        |d	      5 }|D ]E  }d
|v sd|v s|j                  d|      }|s"t        |j                  d            c cddd       S  	 ddd       y# 1 sw Y   yxY w# t        $ r Y yw xY w)uB   태스크 파일에서 작업 레벨(Lv.N)을 파싱. 기본값 2.r   NWORKSPACE_ROOT/home/jay/workspacememorytasks.mdutf-8encodingu   작업 레벨zLv.z	Lv\.(\d+)r4      )rer#   environgetr$   r%   r&   searchr'   groupr*   )r   rL   workspace_root	task_filer.   linems          r/   _get_task_levelrU   i   s    ZZ^^$46KLN^Xw7)3PI)g. 	/! /"d*u}		,5A"1771:.	/ 	//	/ 	/   sN   B9 
B-#B-(B-=B-	B9 "B-$B9 -B62B9 6B9 9	CCc                    d}t         j                  j                  ||  d      }	 t        |d      5 }|D cg c](  }|j	                         st        j                  |      * }}ddd       D cg c]0  }t        j                  t        |j                  dg                   2 c}S c c}w # 1 sw Y   JxY wc c}w # t        t
        j                  t        f$ r g cY S w xY w)uB   이전 FAIL한 verifier 이름 목록 반환 (jsonl 파일에서).r    .fail_history.jsonlrNfailed_names)r#   r$   r%   r&   r)   jsonloadsdumpssortedrN   r*   JSONDecodeErrorOSError)r   r,   history_filer.   rS   entrieses          r/   _get_failed_check_historyrc   z   s    BK77<<y8K-LML,$ 	G45FDtzz$'FGF	G HOO!

6!%%";<=OO G	G 	G Pt33W= 	sK   C B0B+B+%B0'C 35B<(C +B00B95C  C$#C$rY   c                 n   d}t        j                  |d       t         j                  j                  ||  d      }t	        j
                         j                  d      t        |      d}t        |d      5 }|j                  t        j                  |d	      d
z          ddd       y# 1 sw Y   yxY w)u5   이번 FAIL의 verifier 이름들을 jsonl로 append.r    Tr2   rW   %Y-%m-%dT%H:%M:%S)	timestamprY   aFensure_ascii
N)r#   r6   r$   r%   r   nowstrftimer]   r&   r7   rZ   r\   )r   rY   r,   r`   entryr.   s         r/   _record_failed_checksrn      s    BKKKd+77<<y8K-LML\\^,,-@A|,E 
lC	  >A	

5u5<=> > >s   8*B++B4detailsc                    d|  d}t         j                  j                  |      sy	 d}|dz  }|dd D ]  }|d| dz  } t        |d	      5 }|j	                  |       ddd       y# 1 sw Y   yxY w# t
        $ r Y yw xY w)
u%   보고서에 미해결 이슈 기록.z#/home/jay/workspace/memory/reports/rG   Nu)   

## 미해결 이슈 (QC 자동 기록)
u!   - pyright_check 3회 연속 FAIL
   z  - rj   rg   )r#   r$   isfiler&   r7   r_   )r   ro   report_path
issue_textdetailr.   s         r/   _append_unresolved_issuerv      s    7yDK77>>+&C
:;
bqk 	,FD++J	,+s# 	 qGGJ	  	  	  s/   &A5 A) A5 )A2.A5 2A5 5	B Bc                     t         j                  j                  t        d      } dt        v ryt         j                  j	                  |       s0t        dt        j                         t        j                  d       t         j                  j                  |       }t         j                  j                  ddd      }|j                  |      s4t        d	| d
t        j                         t        j                  d       t         j                  j                  | d      }t         j                  j                  |      rddl}|j                  |d       yy)u   verifiers 디렉토리가 shared/verifiers를 가리키는 symlink인지 검증.

    INTEGRITY_FAIL 시 모든 verifier 실행 거부.
    dev8은 독립 구조 허용으로 예외.
    2026-04-17 에이전트 미팅 합의.
    	verifiersz/dev8/NuW   INTEGRITY_FAIL: verifiers 디렉토리가 shared로의 심볼릭 링크가 아닙니다filerK   teamssharedue   INTEGRITY_FAIL: verifiers 심볼릭 링크가 shared/verifiers를 가리키지 않습니다 (실제: )__pycache__r   T)ignore_errors)r#   r$   r%   	_THIS_DIRislinkprintsysstderrexitrealpathendswithisdirshutilrmtree)verifiers_dir	real_pathexpected_suffixpycache_dirr   s        r/   _check_verifiers_integrityr      s     GGLLK8M 9 77>>-(e	
 	   /Iggll7HkBOo.!{!%	

 	 '',,}m<K	ww}}[!k6 "    )r   r	   r   r   r   full_suite_checkr   r   r   r   r   r   r   r   r   r   r
   r   r   r   r   gemini_review_checkr   >   r	   r   r   r   r   )r   r   r   r   r   r   r   r   r	   )TestedReadableUnifiedSecured	Trackabler   c                  v   t        j                  dt         j                        } | j                  ddd       | j                  ddd	
       | j                  ddd
       | j                  ddd
       | j                  ddd
       | j                  ddd
       | j                  ddd
       | j                  ddd
       | j                  ddd
       | j                  ddd
       | j                  ddd
       | j                  dddd !       | j                  d"d#d$
       | j	                         S )%Nu4   QC Verifier — post-task 자동 검증 스크립트)descriptionformatter_classz	--task-idTu!   검증할 task ID (예: task-4.4))requiredhelpz
--api-base u.   API 베이스 URL (예: http://localhost:8000))defaultr   z--api-endpointsuB   콤마 구분 엔드포인트 목록 (예: /api/status,/api/stats)z
--test-diru   pytest 실행 디렉토리z--check-filesu)   콤마 구분 추가 파일 경로 목록z--expected-filesu6   scope_check: 콤마 구분 예상 변경 파일 목록z--expected-files-fromuM   scope_check: 예상 변경 파일 목록 파일 경로 (한 줄에 하나씩)z--skipuJ   건너뛸 check 이름 목록 (콤마 구분, 예: api_health,test_runner)z--outputu&   결과를 저장할 JSON 파일 경로z--workers-diruV   Worker 베이스 디렉토리 (기본: /home/jay/workspace/teams 하위 자동 감지)z--schemas-diruR   JSON Schema 파일 디렉토리 (기본: /home/jay/workspace/teams/shared/schemas)z--gate
store_trueFu=   QC 게이트 모드: PASS/WARN 시 .done 파일 자동 생성)actionr   r   z--teamz	dev1-teamu3   팀 ID (--gate 모드에서 .done 파일에 기록))argparseArgumentParserRawDescriptionHelpFormatteradd_argument
parse_args)parsers    r/   r   r      s   $$J <<F 0  
 =  
 Q  
 )  
 8  
 E  
 \  
 Y  
 5  
 e  
 a  
 L	   B  
 r   rawc                     | sg S | j                  d      D cg c]#  }|j                         s|j                         % c}S c c}w )u@   콤마로 구분된 문자열을 파싱하여 빈 항목 제거.,)splitr)   )r   items     r/   _parse_listr   <  s4    	%(YYs^DTtzz|DJJLDDDs
   AAchecksc                    dddddd}| j                         D ],  }|j                  dd      }|j                  |d      dz   ||<   . g }dD ]$  }||   dkD  s|j                  ||    d|        & |rdj                  |      S dS )	uL   checks 결과에서 PASS/FAIL/SKIP/WARN/MANUAL_SKIP 카운트 요약 생성.r   )PASSFAILSKIPWARNMANUAL_SKIPstatusr   r4    , zno checks ran)valuesrN   appendr%   )r   countsresultspartslabels         r/   
_summarizer   C  s    AqKF--/ )JJx(JJq!$q(q	) E@ 5%=1LLF5M?!E7345  %499U9/9r   	skip_listc                     | j                         D cg c]  }|j                  dd       }}d|v ryd|v sd|v ryyc c}w )u^   전체 결과 결정: 하나라도 FAIL이면 FAIL, WARN/MANUAL_SKIP이면 WARN, 그 외 PASS.r   r   r   r   r   r   )r   rN   )r   r   rX   statusess       r/   _determine_overallr   Q  sL    17AAh'AHA]h6 Bs   =workers_dirc                     ddl }| r| nd}t        j                  j                  |dd      }t        j                  j                  |ddd      }t	        |j                  |      xs |j                  |            S )u   
    workers_dir 하위에 models.py 가 하나라도 있으면 True.
    schema_contract 자동 활성화 판단에 사용.
    r   Nz/home/jay/workspace/teams*z	models.py)globr#   r$   r%   bool)r   _globbasepattern1pattern2s        r/   _has_workersr   [  sa    
 %;+FDww||D#{3Hww||D#sK8H

8$<

8(<==r   check_filesc           
      p   t         j                  j                  dd      }g }| D ]  }t         j                  j	                  |      }t         j                  j                  |      d   }|j                  d      rW|j                  d      sit         j                  j                  |      }g }|j                  t         j                  j                  |dd| d             |r4|j                  t         j                  j                  |dd| d             |r[t         j                  j                  |      }|r:t         j                  j                  |dd| d      }	|	|vr|j                  |	       |D ]8  }
t         j                  j                  |
      s#|
|vs(|j                  |
       :  |S )u=   --check-files에서 관련 테스트 파일을 자동 추론.rC   rD   r   test_z.pytests)r#   rM   rN   r$   basenamesplitext
startswithr   r@   r   r%   rr   )r   rQ   inferredfilepathr   name_no_extdirpath
candidatesparent
candidate3	candidates              r/   _infer_test_filesr   h  s{   ZZ^^$46KLNH "+77##H-gg&&x03 w'  '''//(+ 
 	"'',,~w%}TW@XYZ bggll7Gu[MQT=UVW WW__W-FWW\\&'U;-s;ST
Z/%%j1 $ 	+Iww~~i(Yh-F	*	+A"+H Or   nameapi_baseapi_endpointstest_dir
file_pathsschemas_direxpected_filesgatec                 v
   | |v r^| dk(  r"t        dt        j                         dddgdS | t        v r)t        d|  d	t        j                         d
d|  dgdS ddgdS 	 | dk(  rt	        j
                  ||      S | dk(  rt        j
                  |||
      S | dk(  rt        j
                  |      S | dk(  r|r0t        dt        j                         t        j
                  |      S |rvt        |      }|sddgdS t        dt        |       dt        j                         |D ]   }t        d| t        j                         " t        j
                  |      S ddgdS | dk(  rFt        j
                  d      }|j                  d      d
k(  rd|d<   |d   j                  d d!       |S | d"k(  r=|r|nd#}t        |      sdd$gdS i }|r||d%<   |r||d&<   t        j
                  |fi |S | d'k(  r4t        |      d(k  rdd)d*| d+gd,S t!        j
                  ||xs d#-      S | d.k(  rt#        j
                  |d/0      }t$        rt'        | d1d2d34      }|j                  d      d
k(  rw|j)                  d5j+                  |j                  dg       d#d3       d.|j                  d      d6      }|t,        j.                  k(  rt1        ||j                  dg              |S |j                  d      d7k(  r|j3                          |S | d8k(  rt5        j
                  |      S | d9k(  rt7        j
                  |	xs g |      S | d:k(  rt9        j
                  |      S | d;k(  rt;        j
                  |      S | d<k(  rt=        j
                  |      S | d=k(  rt?        j
                  |      S | d>k(  rct@        dd?gdS tB        jD                  j+                  tB        jF                  j                  d@dA      dBdC|      }tA        j
                  ||D      S | dEk(  r!tH        ddFgdS tI        j
                  |      S | dGk(  rtK        j
                  |      S | dHk(  rtM        j
                  |      S | dIk(  rtO        j
                  |      S | dJk(  rtQ        j
                  |      S | dKk(  rtS        j
                  |      S | dLk(  rtU        j
                  |      S | dMk(  rtW        j
                  |      S ddN|  gdS # tX        $ r,}d
dO|  dPt[        |      j\                   dP| gdcY d#}~S d#}~ww xY w)Qu0   단일 check를 실행하고 결과 dict 반환.r   uz   [QC] ⚠️ test_runner SKIP 사용됨. QC 원칙 위반 가능성. --check-files 기반 자동 추론을 사용하세요.ry   r   u(   ⚠️ test_runner: MANUAL_SKIP (경고)uR   QC 원칙 위반 가능성. --check-files 기반 자동 추론을 사용하세요.)r   ro   z[QC] ERROR: 'u.   '은 MANDATORY 체크입니다. --skip 불가.r   zMANDATORY check 'z' cannot be skippedr   zSkipped via --skip flagr   r	   )r   r   	skip_doner   uj   [QC] ⚠️  --test-dir 사용 감지. 가능하면 --check-files 기반 자동 추론을 사용하세요.uX   --check-files 기반 자동 추론 결과: 관련 테스트 파일 0개. 정당한 SKIP.u9   [QC] test_runner: --check-files 기반 자동 추론 → u   개 테스트 파일 발견z	[QC]   - )
test_filesz*No test directory or check-files specifiedr   T)
full_suiter   r   ro   r   uD   ⚠️ full_suite FAIL → WARN 변환 (기존 실패 포함 가능)r   NzrNo workers found (no models.py detected); schema_contract check skipped. Use --workers-dir to specify a directory.workers_base_dirr   r   rK   u   Lv.1 작업은 tdd_check 면제ztask u<   : 작업 레벨 Lv.1 — tdd_check SKIP (QC-RULES.md 기준))r   reasonro   )r   r   <   )r   timeout_pyright_checkautofix   )strategy_type	thresholdz; )messagesourcero   r   r   r   r   r   r   r   r   z png_check verifier not availablerC   rD   rE   outputs)
output_dirr   z&claude_md_check verifier not availabler
   r   r   r   r   r   r   zUnknown check: zUnhandled exception in : )/r   r   r   MANDATORY_CHECKSr   verifyr	   r   r   r   lenrN   insertr   r   rU   r   r   _CB_AVAILABLEr   record_errorr%   r   ESCALATErv   record_successr   r   r   r   r   r   r   r#   r$   rM   r   r
   r   r   r   r   r   r   	Exceptiontype__name__)r   r   r   r   r   r   r   r   r   r   r   inferred_filestfr   effective_workers_dir	sc_kwargscbr   output_dir_pathrb   s                       r/   	run_checkr    s    y=  MZZ
 (>h  ##M$'UV]`]g]gh$4EdVK^2_1`aa .G-HIIZ
<$$X}==\!$$WW[\\%%!((11]" A #))(33 !2:!>%"($~#  OPSTbPcOdd  A ) =BIbT*<="))^DD %2^1_``'' ''48F zz(#v-#)x y!((,rsM&&3>KD!,$D   I0;	,-+6	-("))'?Y??[ w'!+"(4Uejkrjs  tp  dq  cr  s  s##G9KtLL_$"))ZLF+i~."+
 ::h'61__#'99VZZ	2-Fr-J#K"1#)::i#8. F
 !8!880&**YPR:ST M ZZ)V3%%'M]"%%j11]"%%n&:GDD^#&&w//&&"))'22&&"))'22''#**733[  "(6X5YZZ ggll

/1FG	O ##GHH&&&"(6^5_``"))'22--)0099^#&&w//--)0099_$ ''00&&"))'22))%,,W55%%!((11 %OD62J1KLL 
1$r$q':J:J9K2aSQR
 	

s   $T ?T T 66T -T A"T %T +A
T 6T %T 8T T 1B=T /%T T /T T (T T T 6T AT T /T T T 8T T ,T T  T :T 	T8!T3-T83T8r   teamskippedc                 Z
   | j                  dd      }t        j                  j                  dd      }t        j                  j	                  |dd| d      }t        j                  j                  |      r%t        d| d	t        j                  
       d| d<   y|dv rt        j                  j	                  |dd| d      }t        j                  t        j                  j                  |      d       |||t        j                         j                  d      | j                  di       j                         D 	ci c]  \  }}	||	j                  dd       c}	}|xs g d}
t        |dd      5 }t!        j"                  |
|dd       ddd       t        d| d| t        j                  
       y| j                  di       }|j                         D 	cg c]#  \  }}	|	j                  d|	v rdndd      dk(  s"|% }}}	|j                         D 	cg c]  \  }}	|	j                  dd      dk(  s| }}}	t%        |      }t'        ||       t!        j(                  t+        |            }|j-                  |      dz   }|dk\  r:|r7t        j                  j	                  |dd| d       }t        j                  t        j                  j                  |      d       ||d!d"j	                  t+        |             t+        |      |t        j                         j                  d      d#}t        |dd      5 }t!        j"                  ||dd       ddd       t        d$| d%| d&d"j	                  t+        |             t        j                  
       t        d'| t        j                  
       d(| d<   yt/        |      }|dk\  rt        j                  j	                  |dd| d       }t        j                  t        j                  j                  |      d       ||d)|t        j                         j                  d      d*}t        |dd      5 }t!        j"                  ||dd       ddd       t        d$| d+| d,t        j                  
       t        d-| t        j                  
       d(| d<   yt        d.| d/t        j                  
       yc c}	}w # 1 sw Y   kxY wc c}	}w c c}	}w # 1 sw Y   xY w# 1 sw Y   xY w)0uD   --gate 모드: .qc-result 생성. .done은 finish-task.sh가 담당.overallr   rC   rD   rE   eventsz
.cancelledz
[QC] task uB    CANCELLED — .qc-result 생성 스킵 (.cancelled 마커 발견)ry   	CANCELLEDN)r   r   z
.qc-resultTr2   re   r   r   r   )r   r	  	qc_resultrf   checks_summaryskipped_checksr5   rH   rI   FrK   ri   indentz
[QC] Gate u    — .qc-result 파일 생성: r4   r   z	.escalateu"   동일 verifier 3회 연속 FAIL: r   )r   r	  r   failed_verifierssame_fail_countrf   u   [QC] ⚠️ u    동일 verifier u   회 연속 FAIL: uB   [QC] Gate ESCALATE (동일 사유) — 에스컬레이션 파일: r   u   재시도 3회 초과)r   r	  r   retry_countrf   u    재시도 u!   회 초과. 아누 판단 필요.uJ   [QC] Gate ESCALATE — .done 파일 미생성. 에스컬레이션 파일: u   [QC] Gate FAIL (재시도 u<   /3) — .done 파일 미생성. 수정 후 재실행 필요.)rN   r#   rM   r$   r%   existsr   r   r   r6   r@   r   rk   rl   itemsr&   rZ   dumprc   rn   r\   r]   r9   rA   )r   r   r	  r
  r  	workspacecancelled_pathqc_result_pathkvqc_result_datar.   r   rY   historycurrent_key
same_countescalate_pathescalate_datar  s                       r/   _handle_gater%  Q  s   jjF+G

/1FGI WW\\)XxG9JAWXN	ww~~n%
7)#efmpmwmwx'y""i8yPZE[\
BGGOON3dC !001DEFLjjQY[]F^FdFdFfgdaq!%%&"99g%m
 .#8 	GAIInaeAF	G
7)#B>BRSZ]ZdZde Hb)&,lln{da9XY>i_gio8ptz8z{{&,llnZdah8OSY8YZZ ,G4g|4jj!56]];/!3
?|GGLLHh7)S\H]^MKK6F">tyyP\I]?^>_`$*<$8#-%\\^445HIM mS7; Jq		-qIJwi'8DUVZV_V_`fgs`tVuUvwZZ VWdVefmpmwmwx *F9 6g>Ka "Y(wiW`La bBGGOOM:TJ& 5#.!)!8!89L!M! -w? N1IImQU1MNWI[Efgnqnxnxybcpbqry|  zD  zD  E$.y!2;-?{|  DG  DN  DN  Ou h	G 	G |Z(J J*N NsB   S58S;!#TTT=TT-T!;TT!T*c                     i }t         j                         D ]B  \  }}d}|D ].  }| j                  |i       }|j                  dd      }|dk(  s-d}0 ||d||<   D t        dd|d	<   |S )
uX   TRUST 5차원 요약 생성. 각 차원 내 모든 verifier가 통과해야 passed=True.Tr   r   r   F)rx   passedu   TRUST 외 독립 실행)rx   note_independent)	TRUST_MAPr  rN   TRUST_INDEPENDENT)r   summary	dimensionrx   
dim_passedr  r   r   s           r/   _build_trust_summaryr/    s    G ) 1 

	9
 	#AZZ2&FZZ&1F"
		# # 
	

 ')GN Nr   c                 0   t        |g       }| t        j                         j                  d      ||t	        |      d}t
        j                  j                  dd      }t
        j                  j                  |dd      }	 t        |dd	      5 }t        j                  |      }d
d
d
       j                  di       j                  dd      rt        |      |d<   t!        |       |d<   |S # 1 sw Y   IxY w# t        t        j                  f$ r Y 7w xY w)u!   최종 출력 JSON 구조 생성.re   )r   verified_atr  r   r,  rC   rD   z.claudezfeature_flags.jsonrX   rH   rI   Nflagstrust5_tagging_enabledFtrust_summaryr  )r   r   rk   rl   r   r#   rM   rN   r$   r%   r&   rZ   loadr/  r*   r^   r>   )r   r   r  r   _ws_ff_path_f_ff_datas           r/   build_resultr:    s     ,G||~../BCf%F **..)+@
ACww||C,@AH(C'2 	%byy}H	%<<$(()A5I&:6&BF?# 2':F=M	% 	% t334 s*   C9 C-%8C9 -C62C9 9DDoutput_pathc                     	 t         j                  j                  |      }|r6t         j                  j                  |      st        j                  |d       t        |dd      5 }t        j                  | |dd       d	d	d	       t        d
| t        j                         y	# 1 sw Y   (xY w# t        $ rP}t        d| d| dt         j                  j                  |      xs d dt        j                         Y d	}~y	d	}~ww xY w)u    결과를 JSON 파일로 저장.Tr2   r5   rH   rI   FrK   r  Nz[QC] Result saved to: ry   u)   [QC] ERROR: 결과 파일 저장 실패: r   uJ   . 디렉토리 존재 여부와 쓰기 권한을 확인하세요. 'ls -ld r!   u*   ' 명령으로 확인할 수 있습니다.)r#   r$   r@   r  r6   r&   rZ   r  r   r   r   r_   )r   r;  r   r.   rb   s        r/   save_outputr=    s    
-"''..0KK.+sW5 	?IIfaeA>	?&{m43::F	? 	?  
7}Bqc Jww{3:s;;eg 		
 	

s1   A%B4 'B(&B4 (B1-B4 4	D=ADDc                  Z	   t               } | j                  j                         }| j                  j                         }t	        | j
                        }| j                  j                         }t	        | j                        }t	        | j                        }|D cg c]  }|t        v s| }}|rt        ddj                  |       t        j                         t        ddj                  t        t                     dt        j                         |D cg c]  }|t        vs| }}|s|rt        j                          j#                  d      || j$                  ||| j&                  d}	t(        j*                  j                  t(        j,                  j/                  dd	      d
d      }
t)        j0                  |
d       t(        j*                  j                  |
d      }t3        |dd      5 }|j5                  t7        j8                  |	d      dz          d d d        t        d| t        j                         | j:                  j                         }| j<                  j                         }| j>                  j                         }t	        | j@                        }| jB                  j                         }|sH|rF	 t3        |dd      5 }|D cg c]#  }|j                         s|j                         % }}d d d        tG                t        d| t        j                         |r-t        ddj                  |       t        j                         i }tH        D ]j  }t        d| dt        j                         tK        ||||||||||| j&                        ||<   ||   d    }t        d!| t        j                         l tM        ||      }t        t7        j8                  |dd"#             |rtO        ||       | j&                  rtQ        ||| j$                  |$       |d%   d&k(  rd'S d(S c c}w c c}w # 1 sw Y   1xY wc c}w # 1 sw Y   ^xY w# tD        $ r0}t        d| d| d| dt        j                         Y d }~d }~ww xY w))Nu2   [QC] ⚠️  MANDATORY 체크 skip 시도 차단: r   ry   u   [QC] MANDATORY 체크(u   )는 skip할 수 없습니다.re   )rf   r   r	  r  blocked_mandatory	gate_moderC   rD   rE   logsTr2   zqc-skip-log.jsonlrg   rH   rI   Frh   rj   u   [QC] Skip 사용 기록: rX   uG   [QC] WARNING: --expected-files-from 파일을 읽을 수 없습니다: r   u9   . 파일 경로와 읽기 권한을 확인하세요. 'ls u}   ' 명령으로 파일 존재 여부를 확인하거나 --expected-files 옵션으로 직접 파일 목록을 전달하세요.z [QC] Starting verification for: z[QC] Skipping checks: z[QC] Running check: z ...)r   r   r   r   r   r   r   r   r   r   r   r   z
[QC]   -> rK   r  )r
  r  r   r4   r   ))r   r   r)   r   r   r   r   r   skipr   r   r%   r   r   r]   r   rk   rl   r	  r   r#   r$   rM   rN   r6   r&   r7   rZ   r\   outputr   r   r   expected_files_fromr_   r   
ALL_CHECKSr  r:  r=  r%  )argsr   r   r   r   r   r   r   mandatory_in_skip	log_entrylog_dirlog_pathr.   r;  r   r   r   rD  efrS   rb   r   r   r   r   s                            r/   mainrL    s   <Dll  "G}}""$H 2 23M}}""$HT--.JDII&I %.Gq6F1FGGB499M^C_B`ahkhrhrs$TYYv6F/G%H$IIgh	
 !*G1Q6F-FQG	G%!001DEII'!2
	 '',,rzz~~.>@UVX`bhi
Gd+77<<)<=(C'2 	FaGGDJJyu=DE	F)(43::F++##%K""((*K""((*K !!4!45N2288:1
	)3A OR;=!N4$**,!N!NO  	,WI
6SZZH&tyy';&<=CJJOF  6
$ZL5CJJG&'!##)
z 
#H-
6(##**5!6$ '6*F 
$**V%
:;FK(yyVWdiiC y!V+122g H H	F 	F "OO O 	YZmYnnpqrps t*+ ,YZ ZZ 	sl   Q*QQ,Q9*QQ1 Q$Q4QQ$Q1 QQ$$Q.)Q1 1	R*:%R%%R*__main__)r   N)r   r   NF)N)I__doc__r   rZ   r#   r   r   r$   r@   abspath__file__r   r   rx   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   ImportErrorr   utils.circuit_breakerr   r   r   r8   r'   r0   r:   r>   rA   rU   listrc   rn   rv   r   rE  r   r*  r+  	Namespacer   r   dictr   r   r   r   r   r  r%  r/  r:  r=  rL  r  r    r   r/   <module>rW     s     	 
  GGOOBGGOOH56	CHHHHOOAy!     .#)LMc s s C S S 3 3   S S "
s 
tCy 

>3 
>d3i 
>D 
>c D T  $7N
4 g  ?0!""L1	 "N GH&& GTES ET E:t : :t   
>c 
>d 
>(49 (c (f "&{

{
{
 {
 	{

 {
 {
 {
 {
 {
 4K{
 {
 
{
|OO OO OO3 OO OOX\ OOd $ *# t  4
 
3 
4 
$^3c ^3B zCHHTV o  I
  O  !NMs6   $G +G- 2
G; G*)G*-G87G8;H
	H
