
    ~iײ                   P   U d Z ddlm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
Z
ddlmZmZ ddlmZ ddlmZmZmZ  e ee      j*                        Zee	j.                  vre	j.                  j1                  de        eej2                  j5                  dd            Zed	z  d
z  Zed	z  dz  Zedz  dz  Zedz  dz  Zedz  dz  Z edz  dz  dz  Z!dZ"dZ#de$d<   dZ%de$d<   i dh ddddhdddhddhdh dd dd!hd!d"hd"h d#d$d%d"hd%h d&d'h d(d)d*d"hd+h d,d*h d-d.h d/d0d1hd1 e&        e&        e&        e&       h d2h d3d"d4hd5Z'd6e$d7<   h d8Z(d9e$d:<   d|d;Z)d|d<Z*d}d=Z+d~d>Z,d~d?Z-dd@Z.ddAZ/eddB       Z0eddC       Z0dDdEddFZ0ddGZ1dddDdH	 	 	 	 	 ddIZ2ddJZ3dddKZ4ddLZ5ddMddN	 	 	 ddOZ6ddPZ7ddQZ8ddRZ9	 	 	 	 	 	 	 	 	 	 	 	 ddSZ:ddTZ;ddUZ<ddVZ=ddWZ>ddXZ?ddYZ@ddZZAdd[ZBdd\ZC	 d	 	 	 dd]ZDdd^ZEdd_ZFdd`ZGddaZHddbZIddcZJdddZKddeZLddfZMddgZNddhZOddiZPddjZQddkZRddlZSddmZTddnZUddoZVddpZWddqZXddrZYddsZZddtZ[dduZ\ddvZ]ddwZ^ddxZ_ddyZ`dddzZaebd{k(  r e	j                   ea              yy)u_  
taskctl.py — main 진입 단일화 + 상태 enforcement layer (task-2467 Phase A+B 통합)

회장 절대 기준:
    "taskctl을 거치지 않고는 main을 절대 변경할 수 없다."
    "모든 PR은 bot이 생성하고, 인간은 승인만 하며, main 반영은 taskctl만 수행한다."

상태 모델 (14정상 + 5예외 = 19종):
    정상: CREATED → WORKTREE_READY → RUNNING → [HANDOFF_READY →] COMMITTED
          → PR_OPEN → CI_PENDING → GEMINI_PENDING → REVIEW_READY → VERIFIED
          → HUMAN_APPROVED → MERGING → MERGED → DONE
    예외: BLOCKED / CANCELLED / FAILED / ESCALATED / ADMIN_OVERRIDE_USED
    호환: DISPATCHED / ACKED / GUARD_PASS (기존 11상태 backwards-compat)

저장 위치:
    {WORKSPACE}/.tasks/state/<task-id>.json

Evidence:
    {WORKSPACE}/.tasks/evidence/<task-id>/<name>.json

bypass (회장 전용):
    TASKCTL_BYPASS=1 환경변수로 skip. evidence에 강제 기록.

종료 코드:
    0   PASS / 정상 전이
    1   FAIL (가드 차단, 잘못된 전이, evidence 미달, etc.)
    2   internal error (subprocess 실행 실패 등)
    )annotationsN)datetimetimezone)Path)AnyNoReturnoverloadWORKSPACE_ROOTz/home/jay/workspace.tasksstateevidencescriptszguard.shzqc_report_guard.pyzgemini_evidence_verify.pymemoryorchestration-auditzadmin-override.jsonl)zjonghyuk.jeon@gmail.com)zcancel-kill-switchzqc-checkzhidden-path-auditzlock-in-checkzmerge-safety-checkzgemini-review-gatezci/guardguardztuple[str, ...]REQUIRED_CHECKS)CREATEDWORKTREE_READYRUNNINGHANDOFF_READY	COMMITTEDPR_OPEN
CI_PENDINGGEMINI_PENDINGREVIEW_READYVERIFIEDHUMAN_APPROVEDMERGINGMERGEDDONEBLOCKEDRECOVERABLE_BLOCKED	CANCELLEDFAILED	ESCALATEDADMIN_OVERRIDE_USED
DISPATCHEDACKED
GUARD_PASSSTATESr      r(   r'   r   r'   r(   r   r   >   r   r   r   r   r   r   >   r   r   r   r)   r   r   >   r!   r   r   r   >   r!   r   r   r)   r   r   r)   >   r   r   r   >   r   r   r   r   >   r$   r   r"   r   r    >   r$   r   r#   r%   >   r$   r   r   r%   r&   )r#   r$   r&   r!   r"   r%   zdict[str, set[str]]ALLOWED_TRANSITIONS>   r    r$   r#   r&   zset[str]TERMINAL_STATESc                 f    t        j                  t        j                        j	                  d      S )N%Y-%m-%dT%H:%M:%SZ)r   nowr   utcstrftime     @/home/jay/workspace/.worktrees/task-2481-dev4/scripts/taskctl.py_nowr6      s!    <<%../CDDr4   c            	     H   	 t        j                         } 	 t        j                  g ddddt        t                    j                  j                         xs d}|  d| d	S # t        $ r# t        j                  j                  dd      } Y yw xY w# t        $ r d}Y Dw xY w)
NUSERunknowngitconfigz
user.emailT   capture_outputtexttimeoutcwdzunknown@localz <>)getpassgetuser	Exceptionosenvironget
subprocessrunstr	WORKSPACEstdoutstrip)useremails     r5   _actorrR      s    1  +dA3y>
 &, , 	 V2eWA  1zz~~fi01    s#   A$ AB $)BBB! B!c                    t         |  dz  S )N.json)	STATE_DIRtask_ids    r5   _state_pathrX      s    '%(((r4   c                    | j                         D ci c]  \  }}|dk7  s|| }}}t        j                  |ddd      S c c}}w )N	_checksumFT),:)ensure_ascii	sort_keys
separators)itemsjsondumps)r   kvpayloads       r5   _canonical_jsonrf      sE     %B1k1Aq!tBGB::gETjYY Cs
   AAc                x    t        j                  t        |       j                  d            j	                         S )Nutf-8)hashlibsha256rf   encode	hexdigest)r   s    r5   _compute_checksumrm      s*    >>/%077@AKKMMr4   c                @    | dg d g d d d i d d d i d
ddd d ddd d d d ddS )Nr   )
git_diff_shachanged_pathsbranch	pr_numberpr_state	ci_checksguard_sh_resultqc_report_guard_resultmerge_timestamp
exit_codesFusedtsactorrz   r{   r|   reasonaudit_log_offset)rW   current_statetransitionsr   human_approvedbypassadmin_overrider3   rV   s    r5   
_new_stater      s[    " #&*#
   t< $
% r4   c                $   t         j                  dd       | j                  dd        t        |       | d<   t	        | d         }|j                  d      }|j                  t        j                  | dd      d	
       |j                  |       y )NTparentsexist_okrZ   rW   z	.json.tmpF   r]   indentrh   encoding)
rU   mkdirpoprm   rX   with_suffix
write_textra   rb   replace)r   ptmps      r5   _saver      st    OOD4O0	IIk4 *51E+E)$%A
--
$CNN4::e%BWNUKKNr4   c                     y Nr3   rV   s    r5   _loadr      s    +.r4   c                    y r   r3   )rW   allow_missings     r5   r   r      s    JMr4   Fr   c          	     ~   t        |       }|j                         s|ry t        d| d|  dd       	 t        j                  |j                  d            }j                  d	d       }t        |      }||k7  rt        d
|  d| d| dd       ||d	<   |S # t        $ r}t        d| d| d       Y d }~_d }~ww xY w)Nu   state 파일 없음: u    (먼저 'taskctl init u	   ' 실행)   rh   r   u   state 파일 파싱 실패:     → rZ   uJ   checksum 불일치: 외부 수정 의심 (state file tampered).
  task_id=z

  stored=z
  expected=u0   
  → taskctl만 상태 변경 가능합니다.)	rX   exists_diera   loads	read_textrF   r   rm   )rW   r   r   r   excstoredexpecteds          r5   r   r      s    GA88:$QC'>wiyQSTU>

1;;;89 YY{D)F 'H 	 "x  " $>?
 	
  E+L  >+A3eC591==>s   %B 	B< B77B<c                r   t         | z  }|j                  dd       dj                  t        j                        t               t               t        j                         d}|j                  |       || dz  }t        j                  t        |      d      \  }}	 t        j                  |dd	
      5 }t        j                  ||dd       ddd       t        j                   |t        |             y# 1 sw Y   )xY w# t"        $ r' 	 t        j$                  |        # t&        $ r Y  w xY ww xY w)uA   9종 evidence를 .tasks/evidence/<task-id>/<name>.json에 기록.Tr    )commandr|   	timestamppidrT   .tmpdirsuffixwrh   r   Fr   r   N)EVIDENCE_DIRr   joinsysargvrR   r6   rG   getpidupdatetempfilemkstemprL   fdopenra   dumpr   rF   unlinkOSError)	rW   namere   ev_dirrecordpathfdtmp_pathfs	            r5   _save_evidencer     s   G#F
LLL-88CHH%Vyy{	F MM'tfEN"D##FFCLB	YYr31 	?QIIfaeA>	?


8SY'	? 	?  	IIh 	  		sH    D 8C:'D :D?D 	D6D&%D6&	D2/D61D22D6r|   metaforcec          
        | d   }|rn{||k(  r|dv rnq|dv r|t         v ret        d| d| dd       nQt        ||       t        j	                  |t                     }||vr#t        d| d| dt        |      xs d	 d
d       || d<   | j	                  dd      }||t               |xs ddj                  t        j                        dt        t        |z        d}|rd|d<   |r||d<   | d   j                  |       y )Nr   >   r   >   r$   r!   r#   r%   r"   u   비정상 전이: r   u&    (terminal 상태에서 전이 불가)r   u
    (허용: none)rW   r9   taskctlr   r   fromtor{   r|   r   	exit_codeevidence_pathTforcedr   r   )r-   r   _check_forbidden_transitionsr,   rI   setsortedr6   r   r   r   rL   r   append)	r   targetr|   r   r   srcallowedrW   entrys	            r5   _transitionr   $  s,    
 C	36[0	Y	Y/!%cU%x7]^`ab 	%S&1%))#su5 $SEvhjAZTZ@[[\] $E/ii	9-Gf#)88CHH%\G34E hf	-&r4   c                B   |dk(  r| dvrt        d|  dd       |dk(  r| dvrt        d|  dd       |d	k(  r| dk7  rt        d|  d
d       |dk(  r| dk7  rt        d|  dd       | dk(  r|t               vrt        d| dd       | dk(  r|d	k(  rt        dd       yyy)u<   6개 금지 전이를 명시적으로 차단 (회장 §3.9).r   >   r   r   r)   r   u   금지 전이: uF    → VERIFIED (반드시 REVIEW_READY 또는 GUARD_PASS 상태 필요)r   r      r   r)   u>    → HUMAN_APPROVED (VERIFIED 또는 GUARD_PASS 상태 필요)r   u+    → MERGING (HUMAN_APPROVED 상태 필요)r    r   u     → DONE (MERGED 상태 필요)r#   u   금지 전이: CANCELLED → u    (CANCELLED는 terminal 상태)r!   uF   금지 전이: BLOCKED → MERGING (BLOCKED 상태에서 merge 차단)N)r   r   )r   r   s     r5   r   r   L  s     +` `cU"hi	

 !!c1K&KcU"`a	

 s&66cU"MN	

 C8OcU"BC	

 kfCE1+F83RS	

 iFi/T	
 0r4   c                j    t        d|  t        j                         t        j                  |       y )N
[taskctl] file)printr   stderrexit)msgcodes     r5   r   r   y  s"    	Jse
3::.HHTNr4   c                     t        d|         y )Nr   )r   )r   s    r5   	_print_okr   ~  s    	Jse
r4   x   )rB   rA   envc          
         |}|2t         j                  j                  d      }|rt        |      nt        }t        j                  | dd|t        |      i t         j                  |xs i       S )NTASKCTL_CWDTr?   r@   rA   rB   r   )rG   rH   rI   r   rM   rJ   rK   rL   )cmdrB   rA   r   
actual_cwdenv_cwds         r5   _runr     sg     J**../&-T']9
>>
O)rzz)ciR) r4   c                    dD ]'  } t         j                  j                  |       }|s%|c S  t        dz  }|j	                         r	 |j                  d      j                         D ]_  }dD ]X  }|j                  |      s|j                  dd      d   j                         j                  d      j                  d	      c c S  a 	 y y # t        $ r Y y w xY w)
N)BOT_GITHUB_TOKENGH_BOT_TOKENz	.env.keysrh   r   )zBOT_GITHUB_TOKEN=zGH_BOT_TOKEN==r   "')rG   rH   rI   rM   r   r   
splitlines
startswithsplitrO   rF   )env_nametokenv_keyslineprefixs        r5   _load_bot_tokenr     s    8 jjnnX&J ;&H	 **G*<GGI SD SFv.#zz#q1!4::<BB3GMMcRRSS   		s   9C AC C 	CCc            	     v   	 t        j                  g ddddt        t                    j                  j                         } t        j                  j                  ddj                  t                    j                  d      }| |D cg c]  }|j                          c}v S # t        $ r d} Y ow xY wc c}w )Nr:   Tr=   r>    CHAIRMAN_EMAILSr[   )rJ   rK   rL   rM   rN   rO   rF   rG   rH   rI   r   r  r   )rQ   r   es      r5   _verify_chairmanr    s    +dA3y>
 & 	 jjnn.0IJPPQTUG01QWWY000   1s   AB% 
B6%B32B3c                     t         j                         syt        j                  t        j
                        } d\  }}t         j                  d      j                         D ]  }|j                         s	 t        j                  |      }|j                  dd      }t        j                  |j                  dd            }| |z
  j                  }|d	k  r|d
z  }|dk  r|d
z  } |dk\  r||dfS |dk\  r||dfS ||dfS # t        $ r Y w xY w)zWreturns (soft_count_30d, hard_count_90d, status: OK|SOFT_CAP_WARNING|HARD_CAP_EXCEEDED))r   r   OK)r   r   rh   r   r{   r  Zz+00:00   r   Z   r=   HARD_CAP_EXCEEDED   SOFT_CAP_WARNINGr  )ADMIN_OVERRIDE_LOGr   r   r0   r   r1   r   r   rO   ra   r   rI   fromisoformatr   daysrF   )r0   softhardr   rects_strr{   deltas           r5   _check_admin_capr    s   $$&
,,x||
$CJD$",,g,>IIK zz|
	**T"CWWT2&F''sH(EFB2XOOE{	{	 qyT...qyT---t  		s   7A/D	DDc           
     @   t         j                  j                  dd       t               \  }}}t	               | |d||||dz   |dz   d	}t         j                  dd      5 }	|	j                  t        j                  |d	
      dz          d d d        y # 1 sw Y   y xY w)NTr   chairmanr   )	r{   rW   rr   r|   r~   head_shabypassed_checkssoft_count_this_monthhard_count_this_quarterarh   r   Fr]   
)	r  parentr   r  r6   openwritera   rb   )
rW   rr   r~   r  r  r  r  _r  r   s
             r5   _record_admin_overrider#    s     ##D4#@$&MD$f*!%#'!8
C 
	 	 w	 	7 <1	

3U3d:;< < <s   !*BBc                 H    t         j                  j                  dd      dk(  S )NTASKCTL_BYPASSr  1)rG   rH   rI   r3   r4   r5   _bypass_activer'    s    ::>>*B/366r4   c                   t        dddt        |       ddgd      }|j                  dk7  rd	|j                  d
d j	                         iS 	 t        j                  |j                  xs d      S # t
        j                  $ r d	dicY S w xY w)u   gh pr view로 PR 정보 조회.ghprview--jsonzEstate,mergeable,mergeStateStatus,statusCheckRollup,author,headRefNamer  rA   r   errorN{}json_parse_failed)	r   rL   
returncoder   rO   ra   r   rN   JSONDecodeError)rr   procs     r5   _gh_pr_viewr5    s    dFC	NY D !TU+11344.zz$++-.. .,--.s   "A/ /B	B	c            
        t        g d      j                  j                         } t        g d      }|j                  j                         D cg c]  }|j                         s| }}t        g d      j                  j                         }t        g d      j                  }| xs d |xs d |t	        |j                         D cg c]  }|j                         sd c}      dS c c}w c c}w )N)r;   	rev-parsez--abbrev-refHEAD)r;   diffzorigin/main..HEADz--name-only)r;   r7  r8  )r;   statusz--porcelainr   )rq   ro   rp   git_status_porcelain_lines)r   rN   rO   r   len)rq   r9  r   changeddiff_sha	porcelainlns          r5   _collect_git_evidencerA    s    >?FFLLNFCDD++002@Qaggiq@G@0188>>@H56==I.D (D &)y7K7K7M*\QSQYQYQ[1*\&]	  A +]s   C,%C,	C1C1c                &   | sd i d d ddS t        dddt        |       ddgd	      }|j                  d
k7  r'd i d d |j                  dd  j	                         xs ddS 	 t        j                  |j                  xs d      }|j                  d      xs g }i }|D ]m  }|j                  d      xs |j                  d      xs d}|j                  d      xs( |j                  d      xs |j                  d      xs d}|si|||<   o t        D 	ci c]  }	|	|j                  |	d       }
}	|j                  d      |
||j                  d      |j                  d      dS # t
        j                  $ r}d i d d d| dcY d }~S d }~ww xY wc c}	w )Nno_pr_number)rs   rt   	mergeablemerge_state_statuspr_view_errorr)  r*  r+  r,  z2state,mergeable,mergeStateStatus,statusCheckRollupr  r-  r   r/  gh_errorr0  zjson_parse: statusCheckRollupr   contextr  
conclusionr   r:  UNKNOWNMISSINGrD  mergeStateStatus)rs   rt   ci_checks_allrD  rE  )r   rL   r2  r   rO   ra   r   rN   r3  rI   r   )rr   r4  datar   rollupci_mapchkr   rJ  nrequired_maps              r5   _collect_pr_evidencerU    s    r&*^M 	MdFC	NF D ! r&*!%TU!3!9!9!;!IzK 	KSzz$++-. XX)*0bFF &wwv:#'')"4:ggl+ 8swww/? 8*8.7 	%F4L& :IIAAvzz!Y//ILIHHW%!XXk*"hh'9:   S r&*|C5=QS 	SS Js$   #E# F#F6
F FFc                    t         j                         sddddS t        dt        t               | |gd      }|j                  dk(  rd	nd
|j                  |j
                  dd  |j                  dd  dS )NrL     zguard.sh not foundresultr   r   bash   r-  r   PASSFAILrY  r   stdout_tailstderr_tail)GUARD_SHr   r   rL   r2  rN   r   )stagerW   r4  s      r5   _run_guard_shrd  B  sp    ??##AUVVXw7ED OOq0&f__{{45){{45)	 r4   c           
        t         j                         sddddS t        dt        t               d| dt        t              gd	      }|j
                  d
k(  rdnd|j
                  |j                  dd  |j                  dd  dS )NrL  rW  zqc_report_guard.py not foundrX  python3z	--task-idz--workspacer   r-  r   r\  r]  r^  r_  )QC_REPORT_GUARDr   r   rL   rM   r2  rN   r   )rW   r4  s     r5   _run_qc_report_guardrh  N  s    !!###A_``	C(+wsS\~^D
 !OOq0&f__{{45){{45)	 r4   c                H    | syt        d | j                         D              S )NFc              3  &   K   | ]	  }|d k(    yw)SUCCESSNr3   ).0rd   s     r5   	<genexpr>z,_all_required_checks_pass.<locals>.<genexpr>`  s     :!qI~:s   )allvalues)rt   s    r5   _all_required_checks_passrp  ]  s"    :y'7'7'9:::r4   c                   | j                   j                  dd       t        j                  t	        | j                         d      \  }}	 t        j                  |dd      5 }t        j                  ||dd	
       ddd       t        j                  |t	        |              y# 1 sw Y   )xY w# t        $ r' 	 t        j                  |        # t        $ r Y  w xY ww xY w)u1   tempfile + os.replace 를 이용한 atomic write.Tr   r   r   r   rh   r   Fr   r   N)r  r   r   r   rL   rG   r   ra   r   r   rF   r   r   )r   rO  r   r   r   s        r5   _atomic_writerr  h  s    KKdT2##DKK(8HLB	YYr31 	=QIIdAE!<	=


8SY'	= 	=  	IIh 	  		sH   B2 $B&>'B2 &B/+B2 2	C"<CC"	CC"CC"c                   t        | j                        }|j                         rt        d| j                          yt	        | j                        }|d   j                  d dt               t               dj                  t        j                        dt        t        | j                  z        d       t        |       t               }t        | j                  ddj                  t        j                        t               t               |j!                  d      |j!                  d	      d
d
d|j!                  d	      d d
       t        d| j                   d| d       y)Nzalready initialized: r   r   r   r   r   startrq   ro   r  )
r   r|   r{   rq   r  rN   r   r   sharr   zinit u    → CREATED (r   )rX   rW   r   r   r   r   r6   rR   r   r   r   rL   r   r   rA  r   rI   )argsr   r   git_evs       r5   cmd_initrx  }  s   DLL!Axxz)$,,89t||$E	-ITVfh88CHH%A\DLL89! 
 
%L"$F4<<88CHH%f**X&JJ~.zz.)+  dll^>!A67r4   c                    t        | j                        }t        ||t               |       t	        |       t        | j                   d|        y)Nr|   r   u   : → r   r   rW   r   rR   r   r   )rv  r   r   r   s       r5   _simple_transition_cmdr|    sA    $,,EvVXD9	%LfVH-.r4   c                    t        | d      S )Nr'   r|  rv  s    r5   cmd_dispatchr    s    !$55r4   c                    t        | d      S )Nr(   r~  r  s    r5   cmd_ackr    s    !$00r4   c                &   t        | j                        }|d   }|dv r:t        |dt                      t	        |       t        | j                   d       yt        |dt                      t	        |       t        | j                   d       y)Nr   r+   r   r|   u   : → RUNNINGr   r{  rv  r   r   s      r5   cmd_runr    sy    $,,E

 C
77E9FH5eT\\N-01y1	%Lm,-r4   c                    t        | d      S )u<   worktree-ready: CREATED/DISPATCHED/ACKED → WORKTREE_READY.r   r~  r  s    r5   cmd_worktree_readyr    s    !$(899r4   c                    t        | j                        }|d   dk7  rt        d|d    dd       t        |dt	                      t        |       t        | j                   d       y	)
u#   handoff: RUNNING → HANDOFF_READY.r   r   u   handoff 불가: 현재 상태=u    (RUNNING 필요)r   r   r  u   : → HANDOFF_READYr   r   rW   r   r   rR   r   r   rv  r   s     r5   cmd_handoffr    se    $,,E_*-eO.D-EEVWYZ[fh7	%L123r4   c                .   t        | j                        }|d   }|dvrt        d| dd       t               }|j	                  d      xs d}t        | j                  d||j	                  d	g       ||j	                  d
      ddd||d   j	                  d      d	       ||d   d<   |j	                  d
      |d   d
<   |j	                  d	g       |d   d	<   t        |dt                      t        |       t        | j                   d|dd  d       y)uC   commit: RUNNING/HANDOFF_READY → COMMITTED + commit.json evidence.r   >   r   r   u   commit 불가: 현재 상태=u&    (RUNNING 또는 HANDOFF_READY 필요)r   ro   r  commitrp   rq   r   r   rr   )	ro   rp   commit_hashrq   rN   r   r   ru  rr   r   r  u   : → COMMITTED (sha=N   r   )
r   rW   r   rA  rI   r   r   rR   r   r   )rv  r   r   rw  r  s        r5   
cmd_commitr    s#   $,,E

 C
..,SE1WXZ[\"$Fzz.)/RH4<< OR8**X&:&**;7
, 
 )1E*n%"(**X"6E*h)/OR)HE*o&{&(3	%L3HRaL>CDr4   c                   t        | j                        }|d   }|dvrt        d| dd       d}d}d}d}d}d}d	}	t               }
|
j	                  d
      xs d}|
j	                  d      xs d}t        | dd      }|r*t        | dd      st        | dd      }|rt        j                  j	                  d      dk(  }|rt        j                  j	                  d      nd}|r|}n0t        |      }|j	                  d      xs i j	                  dd      }d}|xs d}|j                         j                         }|j                  d      r|dd }|j                  d      r|dd }||v }|s:t        |dt               d|d       t        |       t        d| d|d | d       t        | dd      st        | dd      r6t!               }|sOt#        | j                  d!d"ddd#|dd$d%       t        |dt               d&d'i       t        |       t        d(d       | j                  }d)| j                   d*| }d+| j                   d,}i }|r||d-<   d.}	d/dd0d1|d2|g}t%        ||d34      }|j&                  j                         }|j(                  j                         }|j*                  }|j*                  dk7  rt%        d/dd5|d6d7g|d84      }|j*                  dk(  rj	 t-        j.                  |j&                        }|j	                  d9      }|j	                  d:d      }|j	                  d      xs i j	                  dd      }d}|t#        | j                  d!d;| |j*                  |||dd<       t        d;| d       n|}t%        d/dd5|d6d7g|d84      } | j*                  dk(  rh	 t-        j.                  | j&                        }!|!j	                  d9      }|!j	                  d:|      }|!j	                  d      xs i j	                  dd      }d}"|xs d}#|#j                         j                         }$|$j                  d      r|$dd }$|$j                  d      r|$dd }$|r|$|"v }%n*|#j                  d      xs |#j                  d      xs |$|"v }%|%st#        | j                  d!d=|d>|" d?d|d@| |||dAdB       t        |dt               dC|d       t        |       t        dD|dEd       n't        | dd      st        dFd       | j2                  }d	}	|r||dG   dH<   t        |dIt               d|i       t%        g dJ      j&                  j                         xs d}&t#        | j                  d!| j                  ||&||||xs |	|	||||dK       t        |       t5        | j                   dL| d?       y# t0        $ r Y w xY w# t0        $ r Y w xY w)Muy   pr-open: COMMITTED → PR_OPEN.
    --pr <int>: 기존 PR 번호 입력
    --auto: bot token으로 직접 PR 생성
    r   >   r   r   r   r   u   pr-open 불가: 현재 상태=u"    (COMMITTED 또는 RUNNING 필요)r   Nr  r   manualro   rq   
bot_authorFautor*  TASKCTL_TEST_MODEr&  TASKCTL_PR_AUTHOR_OVERRIDEauthorlogin)zjeon-jonghyuk-taskctl-botzapp/   z[bot]r%   pr_author_not_bot_strict)r~   	pr_authorrz  u'   --bot-author strict 검증 실패: PR #z author=u    — canonical allowlist=pr-openu;   BOT_GITHUB_TOKEN 미설정 — fail-fast (chairman goal #4)zBOT_GITHUB_TOKEN missingT)r.  r   rN   r   ru  rr   bot_token_missingr~   r  uM   pr-open --auto: BOT_GITHUB_TOKEN 미설정 — fail-fast (chairman 명시 #4)[z] zTask z% PR (auto-created by taskctl pr-open)GH_TOKENbotr)  createz--titlez--body<   r   rA   r+  r,  znumber,url,authorr  numberurlu   PR 생성 실패: )r.  r   rN   r   ru  rr   u   PR author bot 검증 실패: z (allowlist=r   znon-bot author: r]  )r.  r   rN   r   ru  rr   r  bot_author_checkpr_author_not_botu   PR author 검증 실패: u    — chairman goal #2 #5u:   pr-open: --pr <번호> 또는 --auto / --bot-author 필요r   rr   r   r;   r7  origin/main)rW   rq   base_shar  rr   pr_urlr  
created_byrN   r   r   ru  u   : → PR_OPEN (PR #)r   rW   r   rA  rI   getattrrG   rH   r5  rO   lowerr   endswithr   rR   r   r   r   r   rN   r   r2  ra   r   rF   r*  r   )'rv  r   r   rr   r  r  
stdout_str
stderr_strr   r  rw  r  rq   _bot_author_strict_args_pr
_test_mode	_override_view_author
_view_data_BOT_ALLOWLIST_a_anorm_is_bot	bot_token
short_desctitlebodyenv_override
create_cmdr4  	find_procpr_info	view_procviBOT_AUTHOR_ALLOWLIST_authorauthor_normis_bot_authorr  s'                                          r5   cmd_pr_openr    s   
 $,,E

 C FF-cU2TUWXY IFIJJIJ"$Fzz.)/RHZZ!'RF !|U;'$">4t,(;<CJHR

'CDX\I((2
 *x 8 >BCCGRP;N#BXXZ%%'F  (w'.GE;fh,F/;"=> e=hZxP\O_ `//=.>@ tVU#wt\5'I#%	4<<V4!%)5  {&(&(;<>%L`bcd\\
DLL>J<0t||n$IJ')'0L$J $ud


 JL"=[[&&(
[[&&(
OO	??atVVX7JK "I ##q("jj)9)9:G 'H 5I$[[3F!(X!6!<" A A'2 NI !I  t||Y1*>!%((#!%9  )*6:  FtVVX7JK "I ##q(I$4$45B "x 0IVVE62F!#!1!7R < <Wb II
  >/rmmo++-!!&)%ab/K(%cr*K'+??M   ) 7%%f-7"66 
 4<<8\RfQgghi$,YK8&&$*	5 	 {&((;+467 %L,YM9QRTUV tT4(MqQGG	
)2j+&yi7HI 78??EEGM2H4<<<<,* -  
%L1)A>?{ ! 4 ! s&   $A)W 0A'W 	WW	W%$W%c                   t        | j                        }|d   }|dk7  rt        d| dd       |d   j                  d      }t	        |      }|d   |d   d<   |d	   |d   d	<   t               }|j                  d
      xs d}t        | j                  d||d	   t        |d	         |d|j                  dd      d|d       t        |dt               d|i       t        |       t        | j                   d| d       y)uH   ci-check: PR_OPEN → CI_PENDING. 8 required CI checks 수집 + ci.json.r   r   u   ci-check 불가: 현재 상태=u    (PR_OPEN 필요)r   r   rr   rs   rt   ro   r  cirF  r   )rr   rt   all_passr  rN   r   r   ru  r   r*  rz  u   : → CI_PENDING (PR #r   )r   rW   r   rI   rU  rA  r   rp  r   rR   r   r   )rv  r   r   pr_npr_evrw  r  s          r5   cmd_ci_checkr    s   $,,E

 C
i.se3DEqI  -D &E$)*$5E*j!%*;%7E*k""$Fzz.)/RH4<<;'-eK.@A))OR0	( 	 |684,G	%L4TF!<=r4   c                (   t        | j                        }|d   }|dk7  rt        d| dd       |d   j                  d      }t	               }|j                  d      xs d	}t
        j                  j                  d
d      }d|d}t        j                         rt        t        dz        }|t        j                  vr t        j                  j                  d|       	 ddlm}	  |	|||      }
t!        |
t"              r|j%                  |
       nt        |
      |d<   n(t)        dt         dt        j*                         d|d<   t-        | j                  d||d|j                  dd      |j                  dd      d	|j                  dd	      d|d	       t/        |dt1               d |i!       t3        |       t5        | j                   d"       y# t&        $ r0}t)        d| t        j*                         d| |d<   Y d}~d}~ww xY w)#uS   gemini-evidence: CI_PENDING → GEMINI_PENDING. evaluate_gate 호출 + gemini.json.r   r   u&   gemini-evidence 불가: 현재 상태=u    (CI_PENDING 필요)r   r   rr   ro   r  GH_REPOJeon-Jonghyuk/dev_workspaceSKIP)hold_block_passr  r   r   )evaluate_gate
raw_resultu@   [taskctl] WARNING: evaluate_gate 호출 실패 (graceful skip): r   u   evaluate_gate 실패: warningNz[taskctl] WARNING: u%    없음 — gemini gate graceful skipu    gemini_evidence_verify.py 없음geminizgemini-code-assistseverity_countr  )	rr   r  app_slugr  r  rN   r   r   ru  r   r*  rz  u   : → GEMINI_PENDING)r   rW   r   rI   rA  rG   rH   GEMINI_EVIDENCE_VERIFYr   rL   rM   r   r   insertgemini_evidence_verifyr  
isinstancedictr   rF   r   r   r   r   rR   r   r   )rv  r   r   r  rw  r  repogemini_resultscripts_dirr  gate_resultr   s               r5   cmd_gemini_evidencer    s   $,,E

 C
l5cU:NOQRS  -D"$Fzz.)/RH::>>)%BCD8>H$UM$$&)i/0chh&HHOOA{+		F<'h=K+t,$$[1.1+.>l+
 	!"8!99^_	
 $Fi 4<<('++,<a@(,,->G##Ir2
, 
 'vxtTlK	%L234/  	FTUXTYZadakakl)?u'EM)$	Fs   !A G 	H!&HHc                    t        | j                        }|d   }|dk7  rt        d| dd       t        |dt	                      t        |       t        | j                   d       y	)
u.   review-ready: GEMINI_PENDING → REVIEW_READY.r   r   u#   review-ready 불가: 현재 상태=u    (GEMINI_PENDING 필요)r   r   r  u   : → REVIEW_READYr   r  r  s      r5   cmd_review_readyr     se    $,,E

 C
23%7OPRST~VX6	%L012r4   c                6   t        | j                        }|d   }|t        v rt        d| dd       t	               }|d   |d   d<   |d   |d   d<   |d   |d   d<   |j                  d      xs d	}|d   j                  d
      }t        |      }|d   |d   d<   |d   |d   d<   |j                  d      |d   d<   |j                  d      |d   d<   d|v r|d   |d   d<   t        d| j                        }|d   |d   d<   ||d   d<   t        | j                        }|d   |d   d<   ||d   d<   |d   |d   d   d<   |d   |d   d   d<   t               }	|d   dk(  xr |d   dk(  }
t        | j                  d|d   |d   |	||j                  dd	      |j                  dd	      |
rdnd||d	       |
r|d v rt        |d!t               ddd"#       nt        |d!t               ddd"#       d|d   d   d<   t        |       t        | j                   d$       | j                  r!t!        t#        j$                  |d%d&'             y|d(v rt        |d)t               d*d+i#       d|d   d   d<   t        |       g }|d   dk7  r|j'                  d,|d           |d   dk7  r|j'                  d-|d           t        | j                   d.d/j)                  |       d0       | j                  r!t!        t#        j$                  |d%d&'             y)1Nr   u   verify 불가: 현재 상태=z (terminal)r   rq   r   ro   rp   r  rr   rs   rt   rD  rE  rF  pre-pushrY  ru   guard_sh_detailrv   qc_report_guard_detailr   rx   verify_guard_shverify_qc_report_guardr\  verifyr`  ra  r   )	ru   rv   hidden_path_auditr  rN   r   r   ru  rr   >   r(   r   r   r   r   r'   r)   r   r   r   r   r)   )guard_shqc_report_guardrz  u)   : verify PASS → GUARD_PASS (= VERIFIED)Fr   r   >   r   r)   r   r   r~   z"verify failed, demoting to PR_OPENz	guard.sh=zqc_report_guard=z: verify FAIL [, ])r   rW   r-   r   rA  rI   rU  rd  rh  _hidden_path_audit_internalr   r   rR   r   r   machiner   ra   rb   r   r   )rv  r   r   rw  r  r  r  guard_evqc_evaudit_resultr  fail_reasonss               r5   
cmd_verifyr    s   $,,E

 C
o,SE=qA"$F"("2E*h(.~(>E*n%)/)@E*o&zz.)/RH  -D &E$)*$5E*j!%*;%7E*k"%*YY{%;E*k".3ii8L.ME**+%-2?-Cj/*Z6H+3H+=E*'(+3E*'( .E27/E*./27E*./9A+9NE*l#$56@Ek@RE*l#$<= /0L 	f$ 	&(Ov%  4<<#H-"'/),,}b1,,}b1"Q
, 
   ! ! |68*0VLN |68*0VLN45j,'1eT\\N"KLM<<$**UqAB
::E9FH"$HI	K01E*l#H-	%L LV#i(:';<=X& .uX.?@Aodii.E-FaHI||djjU1=>r4   c                r   t        | j                        }|d   }|dvrt        d| dd       t        | dd      xs
 t	               }|d   j                  d	      }d}|rWt        j                  j                  d
      }|r|}n3t        |      }|j                  d      xs i j                  d      xs d}d|v r|j                  d      d   n|}t               }	|	j                  d      xs d}
|rW|sUt        | j                  dddd|ddd|
|d	       t        |dt	               ddi       t        |       t        d| dd       |rZ||k(  rUt        | j                  ddd||ddd|
|d	       t        |dt	               ddi       t        |       t        d| dd       d }	 dd!lm}  ||      }|j                   s+d"}t#        d#|j$                   d$t&        j(                  %       d'|d(<   t        | j                  d|xs d)|d*||d"k(  t-        |d   j                  d+i             d'|
ddd|
|t/               d,       t        |d-t	               ||d.       d|d   d/   d0<   t        |       t1        | j                   d1| d       y# t*        $ r t#        d&t&        j(                  %       Y w xY w)2uL   approve: VERIFIED 또는 GUARD_PASS → HUMAN_APPROVED. self-approve 차단.r   r   u   approve 불가: 현재 상태=u$    (GUARD_PASS 또는 VERIFIED 필요)r   byNr   rr   r  r  r  r   r   ro   r  approvalr]  u%   pr_author lookup failed — fail-fastzgh pr view returned no author)	rY  r~   r  approverrN   r   r   ru  rr   r%   r~   pr_author_lookup_failedrz  u-   approve 차단: pr_author 조회 실패 (PR #r   zself-approve detectedu   self-approve 차단zself-approveu,   self-approve 차단: PR author == approver (system)check_approver_identityr  z[WARN] P0-5: u    → manual approval로 분류r   u8   [WARN] lifecycle_guards not found — P0-5 guard skippedTr   r9   r\  rt   )r  r   rY  approval_typer  ci_passgemini_passr  rN   r   r   ru  rr   r{   r   )r   r  rx   approveu   : → HUMAN_APPROVED (by: )r   rW   r   r  rR   rI   rG   rH   r5  r   rA  r   r   r   lifecycle_guardsr  okr   r~   r   r   ImportErrorrp  r6   r   )rv  r   r   r   r  r  r  pr_dataapprover_loginrw  r  r  r  approver_chks                 r5   cmd_approver  n  s   $,,E

 C
,,,SE1UV	

 tT4(4FHH  -D IJJNN#?@	!I!$'G X.4"99'BJdI/2hX^^C(+HN"$Fzz.)/RHIt||Z=&5
2
 
	 	E;fh"$=>	@e<TF!DaHY.0t||Z-"&+
2
 
	 	E;fh"N3	5e;I;aH!L M[<.~>$M 3 344RSZZ #E
4<<+)"&8+,U:->-B-B;PR-STf.   'vx"0=QS12E*l#I.	%L88HJK5  [HszzZ[s   (AJ $J65J6c                    t        | j                        }t        |dt               dt	        | dd       i       t        |       t        | j                   d       y)Nr#   r~   rz  u   : → CANCELLEDr   )r   rW   r   rR   r  r   r   r  s     r5   
cmd_cancelr    sO    $,,E{&(h =>@	%Lo./r4   c                    t        | j                        }t        |dt               d| j                  i       t        |       t        | j                   d| j                   d       y)Nr$   r~   rz  u   : → FAILED (r   r   )r   rW   r   rR   r~   r   r   r  s     r5   cmd_failr    sS    $,,Exvx,.	%LnT[[M;<r4   c                   t        | j                  d      }|U| j                  r/t        t	        j
                  | j                  d ddd             yt        d| j                   d       y| j                  r"t        t	        j
                  |dd	
             yt        d|d           t        d|d           t        dt        |d                 |d   }t        d|j                  d              t        d|j                  d              t        d|j                  d              t        d|j                  d              t        d|d           t        d|d           y)NTr   )rW   r   missingFr  r   z: state file missingr   r   r   ztask: rW   zstate: r   ztransitions: r   r   zbranch: rq   zpr: rr   z
guard_sh: ru   zqc_report_guard: rv   zhuman_approved: r   zbypass: r   )r   rW   r  r   ra   rb   r<  rI   )rv  r   evs      r5   
cmd_statusr    sl   $,,d3E}<<$**)-/=BD E  Jt||n,@AB||djjU1=>  	uY'()*o./01c%"6789::)*+,RVVK()*+
266"34567!"&&)A"B!CDE '7!8 9:;x)*+r4   c                r  & t        | j                        }	 ddlm}m}  || j                        }|d   s)t        | j                  d|       t        d|d    d        || j                        }|d   s)t        | j                  d|       t        d	|d    d       t               }t        | dd      }t        | dd      }	|rdt               t               d|d<   t        dt        j                         	 ddlm}
  |
| j                        }|j"                  s/d|d   d   d<   t%        |       t        d|j&                   d       n|r`t)               st        dd       t+               \  }}}|dk(  rt        d| d d       |d!k(  rYt        d"| d#t        j                         n8|d$   d%k7  r6d|d   d   d<   t%        |       t        d&|d$    d'| j                   d(d       |d$   d)k(  r"d|d   d   d<   t%        |       t        d*d       |d$   d+k(  r"d|d   d   d<   t%        |       t        d,d       t-        d-| j                        }|d.   |d   d/<   ||d   d0<   |d.   d1k7  r)d|d   d   d<   t%        |       t        d2|d3    d4d       t/        | j                        }|d.   |d   d5<   ||d   d6<   |d.   d1k7  r)d|d   d   d<   t%        |       t        d7|d3    d4d       |d   j1                  d8      }|rt3        |      }|d9   |d   d9<   |d:   |d   d:<   |j1                  d;      |d   d;<   |j1                  d<      |d   d<<   |j1                  d;      d=vrE|j1                  d;      4d|d   d   d<   t%        |       t        d>|j1                  d;       d       t5        |d:         s(d|d   d   d<   t%        |       t        d?|d:    d       |d   j1                  d8      }|s"d|d   d   d<   t%        |       t        d@d       t7               }|j1                  dA      xs dB}|	rt               }||d   dC<   d|d   dD<   d|d   d   d<   |d$   d%k(  s|s|rBt9        |dEt               d||dF|G       t%        |       t9        |dHt               ddi|G       nt9        |dHt               d|dI|G       t        | j                  ddJj;                  t        j<                        ddd|dBdB||ddK
       t%        |       t?        | j                   dL| d4       y|d$   d%k(  r+t9        |dEt               ||dM|xs |G       t%        |       n*|s|r&t9        |dEt               ||dMdG       t%        |       |rJt        | ddN      xs dN}tA        | j                  |||dOgP       dt               dQ|d dR|dS<   t%        |       tB        jD                  j1                  dTdU      }dVdWdtG        |      dXdYdZ|g}|r|jI                  d[       tK        |d\d]id^_      }|jL                  |jN                  d`d  |j                  d`d  da|d   db<   dB}|jL                  dk7  rr|jL                  |d   d   d<   |j                  r|j                  d`d  ndB&dc}tQ        &fdd|D              }|r\	 t9        |det               df|jL                   d4&dgd  dhdG       	 tG        tT              }|t        jV                  vr t        jV                  jY                  d|       ddll-m.}  || j                  dEdedf|jL                   dm&dgd   dn| j                   dogtT        p       t        | j                  ddJj;                  t        j<                        |jL                  dBde||jN                  d`d  |j                  d`d  ||ddq
       t%        |       t        dr|jL                   ds&dtd   du| j                   dv|jL                  xs d       t9        |dit               ddj|jL                   idG       t        | j                  ddJj;                  t        j<                        |jL                  dBdi||jN                  d`d  |j                  d`d  ||dw	       t%        |       t        dx|jL                   ds|j                  dtd   |jL                  xs d       t               }||d   dC<   d|d   d   d<   |}tK        dVdydz| d{gd|}      } | jL                  dk(  r2	 tc        jd                  | jN                        }!|!j1                  d~dB      }	 ddlm4}" d }#	 tk        |      }$|$j1                  d      xs d }# |"|||#      }%|%j"                  s{d|d   d   d<   t9        |dit               dd|%j&                   idG       t        | j                  d|%jm                                t%        |       t        d|%j&                   d       |%jn                  j1                  d|      |d   d<   t9        |dHt               ||||d|xs |G       |rt9        |dt               ddidG       t        | j                  ddJj;                  t        j<                        d|dH||jN                  d`d  |j                  d`d  |||d
       t%        |       |rt?        | j                   d| d       yt?        | j                   d| d       y# t        $ r8}t        | j                  d
dd| dd       t        d| d       Y d }~
d }~ww xY w# t        $ r0}d|d   d   d<   t%        |       t        d| d       Y d }~d }~ww xY w# tR        $ r, t9        |dit               ddj|jL                   dkidG       Y w xY w# t        t^        t`        f$ r Y pw xY w# tf        $ r dB}Y w xY w# tf        $ r d }#Y w xY w# t        $ r t        dt        j                         Y w xY w)Nr   check_state_file_present check_done_escalated_coexistencer	  merge_blocked_state_missingu#   merge 차단 (state file missing): r~   r   merge_blocked_coexistenceu   merge 차단 (coexistence): "merge_blocked_guard_v2_import_failFu*   silent_corruption_guard v2 import 실패: silent_corruption_guard_v2r	  r~   r   u$   merge 차단 (P-SC v2 import fail): admindry_runTry   r   u3   ★★★ TASKCTL BYPASS USED — Chairman overrider   )check_bypass_auditr   rx   mergeu   merge 차단 (P0-8): u-   merge 차단 (lifecycle_guards import fail): u<   admin override 차단: 회장(chairman) 자격 검증 실패r
  u1   admin override 차단: HARD_CAP_EXCEEDED (분기 u   회 사용 ≥ 5회)r  u3   [taskctl] WARNING: SOFT_CAP_WARNING — 이번 달 u   회 사용 (soft limit 3회)r   r   u   merge 차단: 현재 상태=u*    (HUMAN_APPROVED 필요. 'taskctl approve u	   ' 먼저)r#   u   merge 차단: state=CANCELLEDr!   u=   merge 차단: state=BLOCKED (HOLD/CONFLICT 시 머지 차단)r  rY  ru   guard_sh_detail_merger\  u+   merge 차단: guard.sh pre-push FAIL (exit=r   r   rv   qc_report_guard_detail_mergeu)   merge 차단: qc_report_guard FAIL (exit=rr   rs   rt   rD  rE  >   N	MERGEABLEu   merge 차단: PR mergeable=u1   merge 차단: 8 required CI checks 미통과 — u7   merge 차단: PR 번호 없음 (taskctl pr-open 먼저)ro   r  rw   merge_dry_runr   )r!  r   r   r   r   )r!  r   r   )
r   r   merge_commit_shars   r  rN   r   ru  rr   r!  u,   : dry-run merge → MERGING → MERGED (PR #)r   r   zadmin overrideself_approve_constraint)rW   rr   r~   r  r  r  r}   r   r  r  r)  r*  z--mergez--delete-branch--repo--adminTASKCTL_INVOKEDr&  r   r  r^  )r   r`  ra  merge_subprocess)zbranch protectionzRequired status checkzrequired status checkzreview requiredzapproving review
unresolvedznot in mergeable statezPull request is not mergeablezmerge state statusrM  r!   DIRTYUNSTABLEBEHINDc              3  &   K   | ]  }|v  
 y wr   r3   )rl  markerra  s     r5   rm  zcmd_merge.<locals>.<genexpr>   s     QV6[0Q   r"   ztransient merge block (exit=8)r~   ra  r$   zgh pr merge exit=z (transient detect failed)append_recovery): .tasks/evidence/z/merge.jsonrW   
from_stateto_stater~   evidence_paths	workspace)
r   r   r(  rs   r  rN   r   ru  rr   	transientuC   merge 차단 (transient → RECOVERABLE_BLOCKED): gh pr merge exit=z stderr=r/  z (use 'taskctl recover z' to retry))	r   r   r(  rs   r  rN   r   ru  rr   u   merge 실패: gh pr merge exit=api/repos//commits/mainr  r-  ru  )check_merge_commit_shabaseRefName)r  base_branchzP0-6 SHA mismatch: merge_sha_failu   merge 차단 (P0-6): r(  u<   [WARN] lifecycle_guards not found — P0-6 SHA check skipped)r*  r   r   r(  r&   zadmin override used)
r   r   r(  rs   r  rN   r   ru  rr   r   z: admin-override merge PR #u/    → MERGING → MERGED → ADMIN_OVERRIDE_USEDz: merged PR #u-    → MERGING → MERGED (taskctl done 필요))8r   rW   utils.silent_corruption_guardr  r  r   r   r
  r'  r  r6   rR   r   r   r   r  r"  r	  r   r~   r  r  rd  rh  rI   rU  rp  rA  r   r   r   r   r#  rG   rH   rL   r   r   r2  rN   any
SystemExitrM   r   r  utils.audit_chairman_recoveryr7  AttributeErrorr   ra   r   rF   rC  r5  as_dictdetail)'rv  r   r  r  sf_chkcoex_chkr   r   r   r!  r"  
bypass_chkr  r  
cap_statusr  r  r  r  rw  r  merge_tsr~   r  	merge_cmdr4  r(  transient_markersis_transient_ws_root_append_recovery
owner_repoapi_procapi_data_check_merge_shapr_base_ref_pr_datasha_chkra  s'                                         @r5   	cmd_merger_    s   $,,E>	
 *$,,7d|4<<)FO6vh7G6HI1M3DLLA~4<<)DhO/0B/CDaH FD'5)EdIu-G&X
h
 	C#**U	K;+DLL9J==;<j!,/8e,Z->->,?@!D 
!OQRS!1!3dJ,,& 46
 ++EdVKghZZ !%5578E*l+G4%L.u_/E.F G<<@LL>T ![078E*l+G4%L0!4!Y.78E*l+G4%LPRST T\\:/7/Aj+,5=j12H'78E*l+G4%L!+./q2 %T\\26;Hoj23<Aj89?f$78E*l+G4%L{+,A/ Z $$[1(.E,1*,=E*j)-2;-?E*k*-2YY{-CE*k*6;ii@T6UE*23yy%-@@99[)5?@E*%l3G<%L5eii6L5MN -U;-?@;<j!,/8eG[)*,   -D34j,'0eFJ"$Fzz.)/RH6/7j+,-1j/*34j,'0!%555y)-%P$& %Lxvx'.$& xvx)-@$& 	t||Wxx) )! /
 	 	eT\\N"NtfTUVW _!11E9FH$*U; /E	+ 	e	5E9FH$*U;	  	e x)9:N>NLL67	
 & $#
 	e ::>>)%BCDtWc$i<MxY]^I#$D __{{45){{45)-E*()
 !37??j,'0 -1KKdkk$%(R
  Q?PQQ	(E#8.J4??J[[\,]1<TU1C"E"&(y>388+HHOOAx0 ! LL(29$//9J#kZ^Z_N`Mab*4<<.D$ (	 4<<88CHH-!__$&1$++de,++de,!!3  %L$$(OO#4H[=O<P Q))-kC $1	 	E868"&77H$IJ	  	t||Wxx) "  kk$%(kk$%(
/
 
	 	e-doo-> ?kk$%()+OO q	
 vH+3E*'(/0E*l#G, J	u
|=9:H a	"zz(//2H'||E26
_O"&	"4(H#<<6>$K #4dLzz78E*l+G4xvx&*=gnn=M(NO"$ 4<<)97??;LM%L((891=070B0BCUWg0hj,-
 xvx FU*:<o' E0"$9:	  4<<88CHH%,++de$++de$+  
%LT\\N"=dVCrst  	T\\N-v5bcd  >t||%IB3%H1L
 	
 	3C591==>6  	K78E*l+G4%L@FJJ		Kp  (E868"*.??PPj,k!l"&( ((2  9 v  	"!	"  	K	  _LSVS]S]^^_s   Bl ;Am ,n 1Bo -1o* p ( o< B4p 	m -mm	n$%nn1ooo'&o'*o98o9<pp 
pp $p65p6c                F	   t        | j                        }|d   dk7  rt        d|d    dd       	 ddlm} |d   j                  d	      }|s&t        | j                  d
ddd       t        dd       t        j                  j                  dd      } |t        |      |      }|d   s)t        | j                  d
|       t        d|d    d       	 ddlm}m}  || j                        }	|	d   s)t        | j                  d|	       t        d|	d    d        || j                        }
|
d   s)t        | j                  d|
       t        d|
d    d       	 dd#lm}m}  || j                        }|j                   s>t        | j                  d$|j#                                t        d%|j$                   d       |d   j                  d	      }|d   j                  d&      xs |d   j                  d'      } || j                  ||      }|j                   s>t        | j                  d(|j#                                t        d)|j$                   d       t        j                  j                  dd      }d-}t'        d.d/d0| d1gd23      }|j(                  dk(  r2	 t+        j,                  |j.                        }|j                  d4d-      }t2        d5z  d6z  }|j5                  d7d78       || j                   d9z  }|j7                  t+        j8                  | j                  t;               |d:dd;<      d=>       t        | j                  d?|t=        |      t;               d-d-d||d   j                  d	      d@       t?        |dAtA               B       tC        |       tE        | j                   dC| dD       y# t        $ r8}t        | j                  ddd| dd       t        d| d       Y d}~-d}~ww xY w# t        $ r8}t        | j                  ddd | d!d       t        d"| d       Y d}~d}~ww xY w# t        $ r8}t        | j                  ddd*| d+d       t        d,| d       Y d}~+d}~ww xY w# t0        $ r d-}Y w xY w)Eu<   done: state == MERGED 검증 + .done 생성 → DONE 전이.r   r   u   done 불가: 현재 상태=u    (MERGED 필요)r   r   )verify_done_preconditionsr   rr   done_blocked_silent_corruptionFz4pr_number missing in state.evidence (P-SC pre-check)r	  r~   u7   done 차단 (P-SC): pr_number missing in state.evidencer  r  r	  u&   done 차단 (P-SC silent_corruption): r~   done_blocked_guard_import_failu'   silent_corruption_guard import 실패: silent_corruption_guardr  u    done 차단 (P-SC import fail): Nr  done_blocked_state_missingu"   done 차단 (state file missing): done_blocked_coexistenceu   done 차단 (coexistence): !done_blocked_guard_v2_import_failuf   silent_corruption_guard v2 (check_state_file_present/check_done_escalated_coexistence) import 실패: r  u#   done 차단 (P-SC v2 import fail): )check_g3_fail_blocks_donecheck_done_g3_pass_evidencedone_blocked_g3_failu   done 차단 (P0-1): r(  ro   done_blocked_g3_evidenceu   done 차단 (P0-2): u    lifecycle_guards import 실패: r  u,   done 차단 (lifecycle_guards import fail): r  r)  r@  rA  rB  r  r-  ru  r   eventsTr   z.done)rW   r{   r(  r   r   rh   r   done)r(  	done_pathr{   rN   r   r   ru  rr   r    r  u   : → DONE (.done: r   )#r   rW   r   rG  ra  rI   r   rG   rH   intr
  r  r  r  ri  rj  r	  rL  r~   r   r2  ra   r   rN   rF   rM   r   r   rb   r6   rL   r   rR   r   r   )rv  r   ra  pr_n_screpo_sc	sc_resultr   r  r  rN  rO  ri  rj  g3_fail_chkpr_n_for_g3head_sha_for_g3g3_pass_chkr  r(  rY  rZ  
events_dir	done_files                          r5   cmd_donerz    s   $,,E_))%*@)AAQR	
:K
#''44<<)IPL  JAN**..,IJ-c'lGD	4<<)I9U9)H:M9NOQRS=l)$,,7d|4<<)EvN5fX6F5GH!L 4DLLA~4<<)CXN.x/A.BCQGF[/=~~4<<)?ATATAVW'(:(:';<a@ J'++K8*!!"45 5Z $$^4 	 2$,,_]~~4<<)C[EXEXEZ['(:(:';<a@ ::>>)%BCD	uv]34H a	"zz(//2H'||E26
 X%0JTD1~U33I

t||46(8:HMVW	Y   4<<,^f:&**;7	* 	 vVX.	%L1)A>?G  :t||%E?uE.H
 	
 	/u5q99:.  = 	t||%H~  @C  D  E1K
 	
 	23%8!<<=8  Ft||%E8>'H
 	
 	;C5A1EEF(  	"!	"s\   B"O BP	 D Q $1R 	P-PP		Q
-QQ
	R-R		RR R c                    ddl m}  || j                        }t        t	        j
                  |dd             |j                  d      rdS dS )u   .tasks/state/{task_id}.json 무결성 검사.

    JSON 출력: exists, readable, json_valid, checksum_present, checksum_match, current_state, issues
    토르-A의 utils/state_repair.py::inspect_state 함수를 호출.
    r   )inspect_stateFr   r   checksum_matchr   )utils.state_repairr|  rW   r   ra   rb   rI   )rv  r|  rY  s      r5   cmd_state_inspectr  !  sA     14<<(F	$**V%
:;

+,13!3r4   c                    ddl m}  || j                  | j                  | j                  t               | j                        }t        t        j                  |dd             |j                  d      rdS dS )	u   state file checksum repair.

    Chairman approval evidence 필수.
    --approved-by-chairman <name>
    --evidence <path>
    --action <recompute_checksum | rollback_to_backup>

    토르-A의 utils/state_repair.py::repair_state 함수를 호출.
    r   )repair_state)approved_by_chairmanr   r|   repair_actionFr   r   r	  r   )r~  r  rW   r  r   rR   actionr   ra   rb   rI   )rv  r  rY  s      r5   cmd_state_repairr  -  sa     0!66mmhkkF 
$**V%
:;

4 1'a'r4   c                    ddl m}  || j                        }t        t	        j
                  |dd             |j                  d      rdS dS )u   repair 후 후속 검증. .verify-pending 마커 제거 시 PASS.

    토르-A의 utils/state_repair.py::verify_consistency 함수를 호출.
    r   )verify_consistencyFr   r   r	  r   )r~  r  rW   r   ra   rb   rI   )rv  r  rY  s      r5   cmd_verify_consistencyr  C  s@    
 6-F	$**V%
:;

4 1'a'r4   c           
     D   t        | j                        }|d   dk7  rt        d|d    dd       |d   j                  d      }|st        dd       t        j
                  j                  d	d
      }g }||d}d\  }}}	 t        dddt        |      d|ddgd      }	|	j                  |	j                  |	j                  }}}d}|dk(  ry	 t        j                  |      }|j                  d      }|j                  d      xs g }|D cg c]  }|j                  d      r| }}|dk(  xr | }|t!        |      d|d<   nd|j%                         xs d!| i|d<   |s|j'                  d"       |d   j                  d#      xs d$}d}|r	 t        dd%d&| d'| d(gd      }|j                  dk(  rt        j                  |j                        }|j                  d)      xs g }|D cg c]:  }|j                  d*      d+k(  r$|j                  d,      d-vr|j                  d.      < }}|D cg c](  }|j                  d*      d+k7  s|j                  d.      * }}| xr | xr t)        |      }t!        |      ||d/|d0<   nd|j                  xs d$d1d i|d0<   ndd2i|d0<   |s|j'                  d3       d}	 dd4lm}  |||      }t)        t/        |d5d            }|t/        |d6d$      d7|d8<   |s|j'                  d:       d}	 t        dddt        |      d|dd;gd      }|j                  dk(  r\t        j                  |j                        }|j                  d<      xs d$}|j                  d=      xs d$} |d>v xs | d?v }|| d@|dA<   nd|j                  xs d$d1d i|dA<   |s|j'                  dB       |rTt3        | j                  dCd||dD       t        dEdFj5                  |       dGt        j6                  |dH      ddI  d       t9        |dJt;               dg dKdLM       	 t        t<              }!|!t>        j@                  vr t>        j@                  jC                  d|!       ddNl"m#}"  |"| j                  ddJdOdP| j                   dQgt<        R       t3        | j                  dSdTddJ|dU       tM        |       tO        | j                   dV       y# t        $ r%}
t        |
      j                   d|
 }Y d}
~
Nd}
~
ww xY wc c}w # t        j"                  $ r}
dd |
 i|d<   Y d}
~
d}
~
ww xY wc c}w c c}w # t        $ r*}
dt        |
      j                   d|
 i|d0<   Y d}
~
d}
~
ww xY w# t0        $ r dd9i|d8<   Y t        $ r*}
dt        |
      j                   d|
 i|d8<   Y d}
~
d}
~
ww xY w# t        $ r*}
dt        |
      j                   d|
 i|dA<   Y d}
~
Od}
~
ww xY w# t0        tH        tJ        f$ r Y vw xY w)Wu  RECOVERABLE_BLOCKED → MERGING 자동 복귀.

    4 조건 모두 충족 시에만 복귀:

    1. review threads all resolved (gh pr view --json reviewDecision,reviewThreads)
    2. required CI all PASS (gh api repos/{repo}/commits/{sha}/check-runs)
    3. Gemini High 0건 (lifecycle_guards.check_gemini_severity)
    4. mergeStateStatus CLEAN 또는 MERGEABLE

    admin override 없이 객관적 4 조건만 평가. 단일 조건 미충족 시 차단.
    r   r"   u   recover 불가: 현재 상태=u    (RECOVERABLE_BLOCKED 필요)r   r   rr   u3   recover 차단: pr_number missing in state.evidencer  r  )rr   r  )r  r  r)  r*  r+  r*  r,  zreviewDecision,reviewThreadsr  r-  : NFr   reviewDecisionreviewThreads
isResolvedAPPROVED)decisionunresolved_countreviewr.  zJSON decode: zgh exit=)review_threads_unresolved_or_not_approvedro   r  r@  rA  z	/commits/z/check-runs
check_runsr:  	completedrJ  >   neutralskippedsuccessr   )totalfailedpendingr  r5  zhead_sha missingrequired_ci_not_all_pass)check_gemini_severityr	  r~   rc  r  zlifecycle_guards not installedgemini_high_present_or_unknownzmergeStateStatus,mergeablerM  rD  >   CLEAN>   r&  )r:  rD  merge_statemerge_state_not_cleanrecover_blocked)r	  failed_conditionsrM  u$   recover 차단: 4 조건 미충족 (r  z
). detail=r  i  r   )r  r  r  r  )recovered_fromconditions_passedrz  r6  z>auto-recover: 4 conditions PASS (review/ci/gemini/merge_state)r9  z/recover.jsonr:  recoverT)r	  r   r   rM  u1   : RECOVERABLE_BLOCKED → MERGING (4 조건 PASS))(r   rW   r   rI   rG   rH   r   rL   r2  rN   r   rF   type__name__ra   r   r<  r3  rO   r   boolr  r  r  r
  r   r   rb   r   rR   rM   r   r   r  rJ  r7  rK  r   r   r   )#rv  r   r  r  r  rM  rc1stdout1stderr1proc1r   	review_okrO  r  threadstr.  r  ci_okproc2cdatarunsrbadr  	gemini_okr  gem_chkmss_okproc4mdatamssrD  rV  rW  s#                                      r5   cmd_recoverr  S  s    $,,E_!66,U?-C,D E+ ,	
   -DBAF::>>)%BCD#%+/>F )C'14THd57

 !& 0 0%,,gW I
ax	@::g&Dxx 01Hhh/52G%,HAEE,4G!HJH!Z/C^I$$'
O F8 $W]]_%H(3%8HIx  !LM Z $$^4:HE	EuvYxjLME 1$

5<<0yy.4" ,0&'uuX+5l+3TT EE&M 
 37YQ!%%/[:X155=YY B7{BT
 Y!& t !(%,,*<"de)DEt  !34t  !;< IE:'$TB$67	gx4
x   !AB FJ4THd35

 q JJu||,E))./52C		+.4"II%Cm)CF/2$KF=!%,u||/Ar45.I$JF=!   !89 t||%6!29
 	
 	2499=N3O2P Qjje<TcBCE	
 y(=+TVW
y>388#HHOOAx(	
 	LL,S"4<<.>  		
 4<<%	-  
%L<<.IJ i  1#Y''(3%01 I ## 	@ '=)>?F8	@*
 Z  	E#S	(:(:';2cU%CDF4L	E&  G#%EFx E#S	(:(:';2cU%CDxE,  J!(T#Y-?-?,@3%*H I}JT 1 s   AS( ?T 
T!T%T AU .?U	-U 3UU AU  9V	 B!W 6A2X (	T1TTT U1
UU	
U 	VVV	WW$W		W	XW??XXXc                   t        | j                        }t        t        t              j                         j                  j                        }|t        j                  vr t        j                  j                  d|       	 ddl
m}m} | j                  }t!        | dd      }	  |t#               |      }t1        | j                  d       |j3                  d      r|d   |d   d<   t)        |       t5        | j                   d| d|j3                  d       d|j3                  d       d| d
       y# t        $ r}t        d| d       Y d}~d}~ww xY w# $ r@}t%        |d	t'               d
d| i       t)        |       t        d| d       Y d}~d}~wt*        $ rW}t%        |d	t'               d
d| i       t)        |       t        dt-        |      j.                   d| d       Y d}~Dd}~ww xY w)u8   handoff-to-bot: 사람 author PR을 bot으로 재작성.r   )handoff_pr_to_botHandoffErroru$   utils.handoff_to_bot import 실패: r   Nr!  F)r  r!  r%   r~   zhandoff_to_bot failed: rz  u   handoff-to-bot 실패: r   z!handoff_to_bot unexpected error: u   handoff-to-bot 내부 오류: r  handoff-to-botnew_prr   rr   u&   : handoff-to-bot 완료 (original_pr=#u    → new_pr=#z branch=
new_branchz	 dry_run=r   )r   rW   rL   r   __file__resolver  r   r   r  utils.handoff_to_botr  r  r
  r   r*  r  r   r   rR   r   rF   r  r  r   rI   r   )	rv  r   
_self_rootr  r  r   rr   r!  mappings	            r5   cmd_handoff_to_botr    s   $,,E T(^++-44;;<J!:&>H WWID)U3GN#%'
" 4<<!17; {{8)0):j+& 
%L<<. "=X1F0G H++l+,IgYa	A
 K  >3C591==>  1E;fh"&=cU$CD	Fe&se,a00 NE;fh"&Gu$MN	Pe-d3i.@.@-AC5I1MM	Ns=   D9 %E 9	EEEH#6FH*AG<<Hc                   t        | j                        }t        t        t              j                         j                  j                        }|t        j                  vr t        j                  j                  d|       	 ddl
m}m}m}m}m} | j$                  }	| j&                  }
t(        j*                  j-                  d      dk(  }|rt(        j*                  j-                  d      nd}|r|}n0t/        |	      }|j-                  d	      xs i j-                  d
d      }	  |d       	  |
       	  ||
       	  |
       d}d}t9        d      D ]r  }t;        dddt        |	      d |
gd!"      }|j<                  dk(  rd#} nC|j>                  d$d jA                         }|dk(  sUtC        d%| t        j>                  &       t |d#k7  rVt1        | j                  d|	||
dd'| d       t3        |dt5               dd(| i       t7        |       t#        d)| d       t1        | j                  d|	||
d#d*       t7        |       tE        | j                   d+|	 d,|
 d-       y# t         $ r}t#        d| d       Y d}~d}~ww xY w# $ rg}t1        | j                  d|	||
dt        |      d       t3        |dt5               dd| i       t7        |       t#        d| d       Y d}~d}~ww xY w# $ rg}t1        | j                  d|	||
dt        |      d       t3        |dt5               dd| i       t7        |       t#        d| d       Y d}~4d}~ww xY w# $ rg}t1        | j                  d|	||
dt        |      d       t3        |dt5               dd| i       t7        |       t#        d| d       Y d}~d}~ww xY w# $ rg}t1        | j                  d|	||
dt        |      d       t3        |dt5               dd| i       t7        |       t#        d| d       Y d}~d}~ww xY w).uE   request-review: PR author=bot, reviewer=사람, self-approval 차단.r   )assert_bot_authorassert_human_actorassert_distinct_actorsassert_allowed_human_approverBotAuthorErroru#   utils.bot_pr_author import 실패: r   Nr  r&  r  r  r  r  T)strictrequest-reviewr]  )rr   r  reviewerrY  r~   r%   r~   zpr_author_not_bot: rz  u   request-review 차단: r   zreviewer_is_bot: u&   request-review 차단 (reviewer=bot): zself_approval: u'   request-review 차단 (self-approval): zreviewer_not_allowed: u#   request-review 차단 (allowlist): r)  r*  editz--add-reviewerr  r-  r\  r/  u3   [taskctl] WARNING: reviewer 추가 실패 (retry): r   u   gh pr edit 실패: zgh_pr_edit_failed: u5   request-review 실패: gh pr edit --add-reviewer → )rr   r  r  rY  z: request-review PASS (PR #z, reviewer=r   )#r   rW   rL   r   r  r  r  r   r   r  utils.bot_pr_authorr  r  r  r  r  r
  r   r*  r  rG   rH   rI   r5  r   r   rR   r   ranger   r2  r   rO   r   r   )rv  r   r  r  r  r  r  r  r   rr   r  r  r  r  r  review_resultlast_stderrattemptr4  s                      r5   cmd_request_reviewr  L  sk   $,,E T(^++-44;;<J!:&=	
 	
 WWIMMH  34;J@J

;<PTI	i([[*0b55grB	
1)D1
@8$
Ay(3
=%h/  MK8 
h4Y1A8L
 ??a"Mkk$%(..0a<G}U\_\f\fg
h t||%5"iX*=k](K8
 	 	E;fh"&9+$GH	JeD[MRTUV 4<<!1	4  
%L9)KPXzYZ[\O  =23%8!<<=&  1t||%5"iXC8
 	 	E;fh"&9#$?@	Be&se,a001  @t||%5"iXC8
 	 	E;fh"&7u$=>	@e5cU;Q??@  At||%5"iXC8
 	 	E;fh"ocU$;<	>e6se<a@@A  =t||%5"iXC8
 	 	E;fh"&<SE$BC	Ee23%8!<<=s|   I/ $
J /L 8	M3 O" /	J8JJLAK<<LM0	AM++M03O8AOO"Q'AQ		Qc                X   t        | j                        }t        j                  j	                  d      rt        dt        j                         t        | dd      }t        | dd      }|s|st        dt        j                         t        | j                  d	| j                  d
dd       	 t        dz  dz  dz  }|j                  j                  dd       |j                  dd      5 }|j                  t!        j"                  t%               | j                  dddddd| j                  d	d      dz          ddd       t)        |dt+               ddi       t-        |       t/        dd        t1        t3        t4              j7                         j                  j                        }|t        j8                  vr t        j8                  j;                  d!|       	 d!d"lm}m }m!}	  t        jF                        }|rvt        dt        j                         t        | j                  d	| j                  d
|d       t)        |dt+               dd%| i       t-        |       t/        d&| d        | j                  }	  |tI               d'      }t        | j                  d	       t-        |       tO        | j                   d.| d/|j	                  d0       d1       y!# 1 sw Y   xY w# t&        $ r Y w xY w# tD        $ r}
t/        d#|
 d$       Y d}
~
9d}
~
ww xY w# 	$ rd}
t        | j                  d	|d(t1        |
      d       t)        |dt+               dd)|
 i       t-        |       t/        d*|
 d        Y d}
~
d}
~
wt&        $ r}
t        | j                  d	|d(tK        |
      jL                   d+|
 d       t)        |dt+               dd,|
 i       t-        |       t/        d-tK        |
      jL                   d+|
 d$       Y d}
~
d}
~
ww xY w)2u   enqueue-merge: admin override 완전 차단 후 merge queue 진입.

    ★ TASKCTL_BYPASS 환경변수는 이 명령에서 명시적으로 무시됨 (fail-closed).
       merge_queue 흐름은 어떤 bypass도 허용하지 않습니다.
    r%  u]   [taskctl] WARNING: TASKCTL_BYPASS=1 감지 — enqueue-merge에서는 무시됨 (fail-closed)r   r   Fno_admin_overrideTu    ★★★ ADMIN OVERRIDE BLOCKEDenqueue-merger!   zDadmin override attempt detected (--admin or no_admin_override=False))rr   rY  r~   r   r   zmerge-queue.jsonlr   r  rh   r   r  enqueueBLOCKED_ADMIN_OVERRIDE)	r{   rr   r  r  r  outcomer  r!  rW   r  r  Nr%   r~   $admin_override_blocked_enqueue_mergerz  u_   ★★★ ADMIN OVERRIDE BLOCKED: enqueue-merge는 admin override를 허용하지 않습니다.r   r   )detect_admin_override_attempt
enqueue_prMergeQueueErroru(   utils.merge_queue_client import 실패: r   zadmin_override_keyword: u"   ★★★ ADMIN OVERRIDE BLOCKED: )r  r  r]  zenqueue_pr_failed: u   enqueue-merge 실패: r  zenqueue_pr_unexpected: u   enqueue-merge 내부 오류: u   : enqueue-merge 완료 (PR #z
, outcome=r  r   )(r   rW   rG   rH   rI   r   r   r   r  r   r*  rM   r  r   r   r!  ra   rb   r6   rF   r   rR   r   r   rL   r   r  r  r   r  utils.merge_queue_clientr  r  r  r
  r   r   r  r  r   )rv  r   
admin_flagr  mq_logr   r  r  r  r  r   override_reasonrr   r  s                 r5   cmd_enqueue_merger    s    $,,E 
zz~~&'k	
 w.J&94@*0szzBt||_\7
 		),AADWWFMMt<S73 /q

&!%  "'7 "$#||
$ !&
' *.
. 
// 	E;fh"$JK	Menpqr T(^++-44;;<J!:&B	
 	
 4CHH=O0szzBt||_%7
 	
 	E;fh"&>>O$PQ	Se1/1BCQGWWIM%'"
6 4<<':	%L<<. {*W[[%;$<A	? c/ /  		"  B7u=qAAB0  	0t||_"#h7
 	
 	E;fh"&9#$?@	Be%cU+Q// 	Mt||_"c++,Bse47
 	
 	E;fh"&=cU$CD	Fe,T#Y-?-?,@3%H!LL	Msi   0?K9 /AK,?K9 $
L	 	L/ ,K61K9 9	LL		L,L''L,/P)4ANP)A?P$$P)c                 d   g d} g d}d}g }g }| D ]d  }	 t        j                  ddd|gt        t              ddd	      }|j                  d
k(  r%|j
                  j                         D ]  }|j                  dd      }|r|d
   n|t        |      dk\  r|d   nddv r9t        fd|D              rNj                  d      r`j                         }	|	j                  d      xsJ |	j                  d      xs7 |	j                  d      xs$ |	j                  d      xs |	j                  d      }
t        fd|D              }|
s|s|j                  |       |j                  |       
 g |sdnd}|||dS # t        $ r}|j                  d|        Y d}~d}~ww xY w)u%  repo 전체 grep으로 금지 패턴 검색. PASS/FAIL 반환.

    회장 §3.8: 주석/docstring/문자열 단순 언급은 violation 아님. 실제 subprocess 호출만 차단.
    code_call_markers: subprocess.run / _run([ / 리스트 형태로 인자 전달 — 실제 호출 패턴.
    )zgh pr createzgh pr mergezgit push origin mainzgit push --force origin mainz&worktree_manager finish --action merge)z.gittestsfixtures
.worktreesnode_modules__pycache__)
zsubprocess.z_run(z_run([z"gh", "pr", "create"z'gh', 'pr', 'create'z"gh", "pr", "merge"z'gh', 'pr', 'merge'
check_callcheck_outputzPopen(r;   grepz-nTr  )rB   r?   r@   rA   r   r\   r   r  r  zscripts/taskctl.pyc              3  &   K   | ]  }|v  
 y wr   r3   )rl  r   r   s     r5   rm  z._hidden_path_audit_internal.<locals>.<genexpr>h	  s     ;33$;;r4  )z.mdz.txtrT   z.logz.jsonlz.ymlz.yaml#z- z* z"""z'''c              3  &   K   | ]  }|v  
 y wr   r3   )rl  mcontents     r5   rm  z._hidden_path_audit_internal.<locals>.<genexpr>w	  s     )R1!w,)Rr4  zaudit_error: Nr\  r]  )rY  
violationswarnings)rJ   rK   rL   rM   r2  rN   r   r   r<  rH  r  rO   r   r   rF   )forbidden_patternsexcludescode_call_markersr  r  patternr4  r   partsstripped
is_commenthas_call_markerr   rY  r  r   s                 @@r5   r  r  A	  s    ZH JH% %5$	5>>g.	N#$D
 !# KK224 ,D JJsA.E',58$D*-e*/eAhrG+t3 ;(;; }}%`a &}}H !++C0 6#..t46#..t46 $..u56 $..u5  '*)R@Q)R&RO! - %%d+7,%5L &V6FJHMM  	5cU344	5s   E F	F/F**F/c                    ~ t               }|d   dk(  rt        d       yt        dt        |d          dt        j
                         |d   D ]   }t        d	| t        j
                         " y
)u@   audit-hidden-paths: repo 전체 grep으로 우회 경로 감지.rY  r\  u*   hidden-path-audit PASS: 우회 경로 0건r   z"[taskctl] hidden-path-audit FAIL: r  u
   건 발견r   z  VIOLATION: r   )r  r   r   r<  r   r   )rv  rY  rd   s      r5   cmd_audit_hidden_pathsr  	  sx    (*Fh6!>?23vl7K3L2MZX::	% 	8AM!%CJJ7	8r4   c                
   | j                   | j                  | j                  t        t        dz        }|t
        j                  vr t
        j                  j                  d|       	 ddlm} t        d	z  d
z  z  t        j                  t        j                        }|j                  d      |j                  d      	 dM	 	 	 dNfd}t        dz  dz   dz  j!                         s |d d       t        d d        dt              \  }}|s<dj#                  |      } |ddj#                  |       d       t        d| d       t%        dddg      }	|	j&                  dk7  rR |d d|	j(                  j+                          d       t        d d|	j(                  j+                          d       j-                  d d!      t        d"z   d# z  j!                         r |d$ d%       t        d& d       d' d# t%        dddg      }
|
j&                  dk(  r |d( d)       t        d* d+d       t%        g d,      }|j&                  dk7  r't        d-|j(                  j+                          d       |j.                  j+                         t        d	z  d
z  z  }|d. dz  dOfd/}t%        dd0d1t              d2d3g      }|j&                  dk7  r1d4|j(                  j+                          } ||       t        |d       dz  d5z  }|j!                         st        dz  d5z  }|j!                         sAt%        dd0d6d7t              g       t%        dd8d9g       d:| } ||       t        |d       t1        j2                  t
        j4                  t        |      d;d<gddd=t              i t6        j8                  d>t        t              i?      }|j&                  dk7  rit%        dd0d6d7t              g       t%        dd8d9g       d@|j&                   dA|j(                  dBd j+                          } ||       t        |d       j-                  dC      t              t              dD|j.                  dEd dF}t;        |       t=        dG dHj-                  dC       dI dJ dK dL        y# t        $ r}t        d| d| dd       Y d}~d}~ww xY w)Puo   takeover: handoff 검증 → 새 worktree+branch 생성 → start_task_guard 자동 호출 → evidence 저장.r   r   )validate_handoffu'   validate_handoff 모듈 import 실패: z
  u9   /validate_handoff.py 파일이 있는지 확인하세요.r   Nr   r   z%Y%m%dT%H%M%SZr/   c                    	 j                  dd       |xs i j                  d      d d 	d| |d
}t        d d	z  |       y # t        $ r Y y w xY w)
NTr   previous_bottask/-r  )
rW   r  new_botfrom_branchr  
started_atts_filenametakeover_statusfailure_reasonfailure_check	takeover-rT   )r   rI   rr  rF   )
r~   r  handoff_data_partialr  evidence_dir_earlyr
  r	  rW   r  ts_isos
       r5   _save_early_failurez)cmd_takeover.<locals>._save_early_failure	  s    	$$TD$A"!5!; @ @ P"* %gYay9$*#+"(!.B ,;-u/MMrR 		s   AA 	AAr   handoffsrT   u   handoff 파일 없음: 1_handoff_existsr   T)rW   rq   check_head_shaworkspace_rootu   handoff 검증 실패: z; 2_validate_handoffu   handoff 검증 실패:
  r;   r7  z--verifyzfrom-branch 'u   ' 존재하지 않음: 3_from_branch_existsr  r  r  r  u#   새 worktree 경로 이미 존재: 5_worktree_path_collisionu/   새 worktree 경로가 이미 존재합니다: r  u   새 branch 이미 존재: 6_branch_collisionu   새 branch 'u_   '가 이미 존재합니다. 다른 bot ID를 사용하거나 기존 branch를 삭제하세요.r  u    origin/main HEAD 조회 실패: r  c                    	 j                  d      
t              t        	      d| d}t        |       y # t        $ r Y y w xY w)Nr  r  )rW   r  r	  r  r  handoff_pathr
  r  new_worktree_pathr  r  r  r  )rI   rL   rr  rF   )r~   r  r  evidence_filer
  handoff_datar  r	  r  r  recorded_headrW   r  r  s     r5   _save_failed_evidencez+cmd_takeover.<locals>._save_failed_evidence
  sj    	" , 0 0 @"$) #L 1*(%():%;$*#+"(B -, 		s   =A 	AAworktreeaddz-br  u   git worktree add 실패: zstart_task_guard.pyremovez--forcerq   z-Du   start_task_guard.py 없음: z--task--botr   r
   r   u   start_task_guard 실패 (exit=r8  r/  r  r  r^  )rW   r  r	  r  r  r  r
  r  r  r  r  r  start_guard_stdoutu   takeover 성공: z
  previous_bot=u    → new_bot=z
  new branch:   z
  new worktree: z
  evidence:     r   )r~   rL   r  rL   r  zdict | NonereturnNone)r~   rL   r)  r*  )rW   r
  r  rL   rM   r   r   r  r  r
  r   r   r0   r   r1   r2   r   r   r   r2  r   rO   rI   rN   rJ   rK   
executablerG   rH   rr  r   ) rv  r  r  r   now_utcr  r	  errors	err_linesr4  proc_branch	proc_mainevidence_dirr#  proc_wtr~   start_guard_script
proc_guardr   r  r  r   r
  r!  r  r	  r  r  r"  rW   r  r  s                       @@@@@@@@@@@@@r5   cmd_takeoverr5  	  s   <<G''K88G i)+,K#((";'
5 #X-
:WDll8<<(G""#34K23F AE2=IM ( x'*4'%7HHL 5l^DFXY&|n5q9/ 	 B KK'	5dii6G5HI0(	* 	))5q9Z=>D!K=(?@Q@Q@S?TU"	

 	K=(?@Q@Q@S?TU	

 !$$Z4M!L0gYay3II!12C1DE'	

 	=>O=PQ	

 	7),J{J
CDK"(5 	

 	:, 'Q R	
 89Iq /	0@0@0F0F0H/IJAN%%'Hx'*4w>L Y{m5#AAM  * z5j	 G Q,W^^-A-A-C,DEf%VQ*Y69NN$$&&25JJ$$&eZ9c:K6LMNeXtZ01/0B/CDf%VQ	/0(GWgV!"<rzz<+S^<J !eZ9c:K6LMNeXtZ01,Z-B-B,C3  '--/02 	 	f%VQ $((8!L)"  !23"$(//6H -*
G9 %&**>:;=	 R%, ',- .(/		+ k  
5cU ;VX	
 	

s   7T 	U "T;;U c                 h   t        j                  dd      } | j                  dd      }d }|j                  dd	
      } ||       |j	                  t
               |j                  dd
      } ||       |j	                  t               |j                  dd
      } ||       |j	                  t               |j                  dd
      } ||       |j	                  t               |j                  dd
      } ||       |j                  dt        d d       |j                  ddd       |j                  ddd       |j	                  t               |j                  dd
      } ||       |j                  ddd        |j	                  t               |j                  d!d"
      } ||       |j                  d#d d$%       |j	                  t               |j                  d&d'
      } ||       |j                  d(dd)       |j                  d*dd+       |j                  d,d d-%       |j	                  t               |j                  d.d/
      } ||       |j                  d,d 0       |j	                  t               |j                  d1d2
      } ||       |j                  d,d3       |j	                  t                |j                  d4d5
      } ||       |j                  ddd6       |j	                  t"               |j                  d7d8
      } ||       |j                  d9d:dd;d<=       |j                  d>dd?@       |j	                  t$               |j                  dAdB
      } ||       |j	                  t&               |j                  dCdD
      } ||       |j	                  t(               |j                  dEdF
      } ||       |j	                  t*               |j                  dGdH
      } ||       |j	                  t,               |j                  dIdJ
      } ||       |j	                  t.               |j                  dKdL
      } ||       |j	                  t0               |j                  dMdN
      } ||       |j	                  t2               |j                  dOdP
      } ||       |j	                  t4               |j                  dQdR
      }|j	                  t6               |j                  dSdT
      } ||       |j	                  t8               |j                  dUdV
      } ||       |j                  dWddX@       |j                  dYddZ@       |j                  d[d\d]gdd^_       |j	                  t:               |j                  d`da
      } ||       |j	                  t<               |j                  dbdc
      } ||       |j                  dt        ddde       |j                  d(df       |j	                  t>               |j                  dgdh
      } ||       |j                  dt        di       |j                  djddk@       |j	                  t@               |j                  dldm
      } ||       |j                  dt        di       |j                  dndddop       |j                  d*ddq       |j	                  tB               | S )rNr   uh   task 상태 enforcement layer + main 진입 단일 경로 (task-2467: 14+5 state machine + PR lifecycle))progdescriptionr   T)destrequiredc                *    | j                  dd       y )NrW   u   task ID (예: task-2467)help)add_argument)sps    r5   _add_taskidz!build_parser.<locals>._add_taskidi
  s    
	(BCr4   initu   CREATED 상태 생성r<  )funcdispatchu    DISPATCHED 전환 (compat alias)acku   ACKED 전환 (compat alias)rK   u   RUNNING 전환r  u<   PR_OPEN 전환 (bot token PR 생성 또는 PR 번호 입력)z--pru   PR 번호 (수동 입력))r  defaultr=  z--auto
store_trueu    bot token으로 직접 PR 생성)r  r=  z--bot-authoru7   bot author로 PR 생성 강제 (--auto의 strict alias)r  uS   evidence 자동 수집 + guard.sh + qc_report_guard, PASS 시 GUARD_PASS(=VERIFIED)z	--machineu   state JSON 출력r  u+   HUMAN_APPROVED 전환 (self-approve 차단)z--byu6   승인자 (human login). 미지정 시 _actor() 사용)rE  r=  r#  u.   main 진입 단일 경로 (MERGING → MERGED)z	--dry-runu,   actual gh pr merge skip — 상태만 전이r+  u1   chairman admin override (audit log 자동 기록)z--reasonu   admin override 사유cancelu   CANCELLED 전환)rE  failu   FAILED 전환)r:  r:  u   현재 상태 + evidence 출력u   JSON 출력takeoveruQ   handoff evidence 기반 봇 인계 — 새 worktree + branch + start_guard 자동z--fromr
  BRANCHu/   이전 봇의 branch (예: task/task-2458-dev4))r9  r:  metavarr=  r'  u   새 봇 ID (예: dev5))r:  r=  zworktree-readyu*   WORKTREE_READY 전환 (dispatch/ack alias)handoffu0   HANDOFF_READY 전환 (RUNNING → HANDOFF_READY)r  u6   COMMITTED 전환 (RUNNING/HANDOFF_READY → COMMITTED)zci-checku/   CI_PENDING 전환 + 8 required CI checks 수집zgemini-evidenceu,   GEMINI_PENDING 전환 + evaluate_gate 호출zreview-readyu5   REVIEW_READY 전환 (GEMINI_PENDING → REVIEW_READY)rn  u3   DONE 전환 (MERGED → DONE + .done 파일 생성)r  uW   RECOVERABLE_BLOCKED → MERGING 복귀 (review/CI/gemini/merge_state 4 조건 PASS 시)zaudit-hidden-pathsuV   repo 전체 grep으로 우회 경로 감지 (gh pr create/merge, git push origin main)zstate-inspectu6   state file 무결성 검사 (checksum, json 유효성)zstate-repairu*   checksum repair (chairman evidence 필수)z--approved-by-chairmanu   승인자 이름z
--evidenceu!   chairman approval evidence 경로z--actionrecompute_checksumrollback_to_backupu   repair 동작 선택)choicesr:  r=  zverify-consistencyu?   repair 후 후속 검증 (.verify-pending 마커 제거 확인)r  u/   사람 author PR을 bot equivalent로 재작성u   원본 PR 번호)r  r:  r=  )r  r  u,   approver=사람 강제, self-approval reject)r  r:  z
--revieweru   사람 GitHub loginr  u3   merge_queue 진입 — admin override 절대 금지z--no-admin-overridezdefault True, fail-closed)r  rE  r=  uD   reject 트리거(테스트용). --no-admin-override와 양립 불가)"argparseArgumentParseradd_subparsers
add_parserset_defaultsrx  r  r  r  r>  rp  r  r  r  r_  r  r  r  r5  r  r  r  r  r  r  rz  r  r  r  r  r  r  r  r  )r   subr@  r?  s       r5   build_parserrV  _
  s   =	A 

	D

9CD 
%<	=BOR__(_3	
)K	LBOR__,_7	$A	BBOR__'_2	$4	5BOR__'_2		(f	gBOOOFd9TOUOOH\8ZO[OON<R  TOOO%	b 
 
dBOOOK;NOOOOO$		(U	VBOOOFD/gOhOOO%	&V	WBOOOKG  IOOIlL  NOOJ3JOKOOO#	'9	:BOOOJO-OOO$	_	5BOOOJO.OOO"	'H	IBOOOK=OIOOO$	` 
 
B OOO}tX>   OOGd1IOJOOO& 
(/[	\BOR__*<_=		(Z	[BOR__+_6	'_	`BOR__*_5	
)Z	[BOR__,_7	)0^	_BOR__*=_>	-d	eBOR__*:_;	%Z	[BOR__(_3 
f 
 
B OR__+_6	,e 
 
gBOO/O0 
.f	gBOR__*;_<	-Y	ZBOOO,tBTOUOOL46YOZOO%';<#	   OO)O*	,3t	uBOR__*@_A 
(/`	aBOOOFt:LOMOOKO5OO+O,	(/]	^BOOOFtO4OOL46KOLOO+O,	.c	dBOOOFtO4OO),4  6OOIl_  aOO*O+Hr4   c                D   t               }|j                  |       }	 |j                  |      }xs dS # t        $ r  t        j
                  $ r}t        d| d       Y d }~6d }~wt        $ r/}t        dt        |      j                   d| d       Y d }~ld }~ww xY w)Nzsubprocess timeout: r   zinternal error: r  r   )
rV  
parse_argsrB  rI  rJ   TimeoutExpiredr   rF   r  r  )r   parserrv  rcr   s        r5   mainr\  
  s    ^FT"D@YYt_ 7N  $$ .#C5)1-- @S	 2 232cU;Q??@s!   4 BA$$B0%BB__main__)r)  rL   )rW   rL   r)  r   )r   dict[str, Any]r)  rL   )rW   rL   r)  r^  )r   r^  r)  r*  )rW   rL   r   r  r)  dict[str, Any] | None)rW   rL   r   rL   re   r^  r)  r*  )r   r^  r   rL   r|   
str | Noner   r_  r   r  r)  r*  )r   rL   r   rL   r)  r*  )r   )r   rL   r   rp  r)  r   )r   rL   r)  r*  )
r   	list[str]rB   zPath | NonerA   rp  r   zdict[str, str] | Noner)  zsubprocess.CompletedProcess)r)  r`  )r)  r  )r)  ztuple[int, int, str])rW   rL   rr   
int | Noner~   rL   r  rL   r  ra  r)  r*  )rr   rp  r)  r^  )r)  r^  )rr   rb  r)  r^  )rc  rL   rW   rL   r)  r^  )rt   zdict[str, str]r)  r  )r   r   rO  r^  r)  r*  )rv  argparse.Namespacer)  rp  r   )rv  rc  r   rL   r   r_  r)  rp  )r)  zargparse.ArgumentParser)r   zlist[str] | Noner)  rp  )d__doc__
__future__r   rP  rD   ri   ra   rG   rJ   r   r   r   r   pathlibr   typingr   r   r	   rL   r  r  _SCRIPTS_DIRr   r  rH   rI   rM   rU   r   rb  rg  r  r  r  r   __annotations__r*   r   r,   r-   r6   rR   rX   rf   rm   r   r   r   r   r   r   r   r   r   r   r  r  r#  r'  r5  rA  rU  rd  rh  rp  rr  rx  r|  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r_  rz  r  r  r  r  r  r  r  r  r  r5  rV  r\  r  r   r3   r4   r5   <module>rj     sH  8 #     	  
  '  * *
 4>(()sxxHHOOA|$  02GHI	 7*	8#j0y :-i'*>>"Y.1LL ),AADZZ .	$ 	 <,8, 7,-, i)*	,
 yk, 8, i-, ), B, #Y/, <, D, !9-, ;, 7,$ :%,& vh',( CE),, e5> I23=, ( D S RE()Z
N: 
 . 
 .	 M 
 M16 <> LP.2#%'+%'%'(,%'P%
Z
 04C&*#/J,.	16<<'<14<<$-< 
<47.& F	;*> ;?"7CF61 :
:GT8.b	"UzbJ<Qr}J	4(,( yB0pv|on>NB(AR[| zCHHTV r4   