
    i                    &   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j&                  j)                  dd            Zed	z  d
z  Zedz  dz  Zedz  dz  ZdZded<   dZded<   dhdhdhdhddhddhdhdh e        e        e       dZded<   h dZded<   dJd ZdJd!Z dKd"Z!dLd#Z"dLd$Z#dMd%Z$dNd&Z%edMd'       Z&edOd(       Z&d)d*dOd+Z&ddd)d,	 	 	 	 	 dPd-Z'dQdRd.Z(dSd/Z)dd0dd1	 	 	 dTd2Z*dUd3Z+	 dV	 	 	 dWd4Z,dUd5Z-dUd6Z.dUd7Z/dUd8Z0dXd9Z1dYd:Z2dZd;Z3dMd<Z4d[d=Z5dUd>Z6dUd?Z7dUd@Z8dUdAZ9dUdBZ:d\dCZ;dUdDZ<d]dEZ=dUdFZ>d^dGZ?dVd_dHZ@eAdIk(  r e	j                   e@              yy)`u  
taskctl.py — main 진입 단일화 + 상태 enforcement layer (task-2449 MVP)

회장 절대 기준:
    "taskctl을 거치지 않고는 main을 절대 변경할 수 없다."

상태 모델 (11종):
    CREATED → DISPATCHED → ACKED → RUNNING → PR_OPEN → GUARD_PASS
        → HUMAN_APPROVED → MERGED → DONE
                                ↘ CANCELLED
                                ↘ FAILED

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

bypass (회장 전용):
    TASKCTL_BYPASS=1 환경변수로 1~5단계 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scriptszguard.shzqc_report_guard.py)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
DISPATCHEDACKEDRUNNINGPR_OPEN
GUARD_PASSHUMAN_APPROVEDMERGEDDONE	CANCELLEDFAILEDSTATESr   r   r   r   r   r   r   r   zdict[str, set[str]]ALLOWED_TRANSITIONS>   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-2463-dev6/scripts/taskctl.py_nowr&   d   s!    <<%../CDDr$   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     r%   _actorr@   h   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    r%   _state_pathrF   |   s    '%(((r$   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       r%   _canonical_jsonrT      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sha256rT   encode	hexdigest)r   s    r%   _compute_checksumr[      s*    >>/%077@AKKMMr$   c                2    | dg d g d d d i d d d i 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)rE   current_statetransitionsevidencehuman_approvedbypassr#   rD   s    r%   
_new_staterp      sG    " #&*#
   t<# r$   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_okrH   rE   z	.json.tmpF   rK   indentrV   encoding)
rC   mkdirpopr[   rF   with_suffix
write_textrO   rP   replace)r   ptmps      r%   _saver      st    OOD4O0	IIk4 *51E+E)$%A
--
$CNN4::e%BWNUKKNr$   c                     y Nr#   rD   s    r%   _loadr      s    +.r$   c                    y r   r#   )rE   allow_missings     r%   r   r      s    JMr$   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	   ' 실행)   rV   rx   u   state 파일 파싱 실패:     → rH   uJ   checksum 불일치: 외부 수정 의심 (state file tampered).
  task_id=z

  stored=z
  expected=u0   
  → taskctl만 상태 변경 가능합니다.)	rF   exists_dierO   loads	read_textr4   r{   r[   )rE   r   r   r   excstoredexpecteds          r%   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<rj   metaforcec          
     f   | d   }|rno||k(  r|dv rne|dv r|t         v rYt        d| d| dd       nEt        j                  |t	                     }||vr#t        d| d| dt        |      xs d	 d
d       || d<   ||t               |xs dd}|rd|d<   |r||d<   | d   j                  |       y )Nrk   >   r   >   r   r   u   비정상 전이: r   u&    (terminal 상태에서 전이 불가)r   u
    (허용: none)taskctlfromtori   rj   Tforcedr   rl   )r   r   r   r7   setsortedr&   append)r   targetrj   r   r   srcallowedentrys           r%   _transitionr      s     
 C	36[0	*	*/!%cU%x7]^`ab%))#su5 $SEvhjAZTZ@[[\] $E/f#)	E hf	-&r$   c                j    t        d|  t        j                         t        j                  |       y )N
[taskctl] file)printsysstderrexit)msgcodes     r%   r   r      s"    	Jse
3::.HHTNr$   c                     t        d|         y )Nr   )r   )r   s    r%   	_print_okr      s    	Jse
r$   x   )r0   r/   envc          
         t        j                  | dd|t        |xs t              i t        j
                  |xs i       S )NTr-   r.   r/   r0   r   )r8   r9   r:   r;   r5   r6   )cmdr0   r/   r   s       r%   _runr      sA    >> y!)rzz)ciR) r$   c                J   t        | j                        }|j                         rt        d| j                          yt	        | j                        }|d   j                  d dt               t               d       t        |       t        d| j                   d| d       y)	Nzalready initialized: r   rl   r   r   zinit u    → CREATED (r   )	rF   rE   r   r   rp   r   r&   r@   r   )argsr   r   s      r%   cmd_initr     s    DLL!Axxz)$,,89t||$E	-ITVfh!  
%Ldll^>!A67r$   c                    t        | j                        }t        ||t               |       t	        |       t        | j                   d|        y)Nrj   r   u   : → r   )r   rE   r   r@   r   r   )r   r   r   r   s       r%   _simple_transition_cmdr     sA    $,,EvVXD9	%LfVH-.r$   c                    t        | d      S )Nr   r   r   s    r%   cmd_dispatchr   (  s    !$55r$   c                    t        | d      S )Nr   r   r   s    r%   cmd_ackr   ,  s    !$00r$   c                    t        | d      S )Nr   r   r   s    r%   cmd_runr   0  s    !$	22r$   c                    t        | j                        }| j                  |d   d<   t        |dt	               d| j                  i       t        |       t        | j                   d| j                   d       y)	Nrm   r`   r   prr   u   : → PR_OPEN (PR #r   r   )r   rE   r   r   r@   r   r   r   r   s     r%   cmd_pr_openr   4  sc    $,,E%)WWE*k"ydggG	%L1$''!<=r$   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*   r   r   )r*   statusz--porcelainr   )r_   r]   r^   git_status_porcelain_lines)r   r<   r=   
splitlineslen)r_   r   r   changeddiff_sha	porcelainlns          r%   _collect_git_evidencer   B  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)ra   rb   	mergeablemerge_state_statuspr_view_errorghr   viewz--jsonz2state,mergeable,mergeStateStatus,statusCheckRollup   r/   r   gh_errorz{}zjson_parse: statusCheckRollupnamecontext 
conclusionr   r   UNKNOWNMISSINGr   mergeStateStatus)ra   rb   ci_checks_allr   r   )r   r:   
returncoder   r=   rO   r   r<   JSONDecodeErrorr7   r   )r`   procdatar   rollupci_mapchkr   r   nrequired_maps              r%   _collect_pr_evidencer   P  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 )Nr      zguard.sh not foundresult	exit_coder   bash   r   r   PASSFAILr   r   stdout_tailstderr_tail)GUARD_SHr   r   r:   r   r<   r   )stagerE   r   s      r%   _run_guard_shr  s  sp    ??##AUVVXw7ED OOq0&f__{{45){{45)	 r$   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 )Nr   r   zqc_report_guard.py not foundr   python3z	--task-idz--workspacer   r   r   r   r   r   r   )QC_REPORT_GUARDr   r   r:   r;   r   r<   r   )rE   r   s     r%   _run_qc_report_guardr    s    !!###A_``	C(+wsS\~^D
 !OOq0&f__{{45){{45)	 r$   c                H    | syt        d | j                         D              S )NFc              3  &   K   | ]	  }|d k(    yw)SUCCESSNr#   ).0rR   s     r%   	<genexpr>z,_all_required_checks_pass.<locals>.<genexpr>  s     :!qI~:s   )allvalues)rb   s    r%   _all_required_checks_passr    s"    :y'7'7'9:::r$   c                $   t        | j                        }|d   }|t        v rt        d| dd       t	               }|d   |d   d<   |d   |d   d<   |d   |d   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<   |d   dk(  xr |d   dk(  }|rvt        |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%                  |	       d+       | j                  r!t        t        j                   |d d!"             y),Nrk   u   verify 불가: 현재 상태=z (terminal)r   r_   rm   r]   r^   r`   ra   rb   r   r   r   pre-pushr   rc   guard_sh_detailrd   qc_report_guard_detailr   rf   verify_guard_shverify_qc_report_guardr   r   )guard_shqc_report_guardr   r   verifyu   : verify PASS → GUARD_PASSFru   rv   >   r   r   r   reasonz"verify failed, demoting to PR_OPENz	guard.sh=zqc_report_guard=z: verify FAIL [z, ])r   rE   r   r   r   r7   r   r  r  r   r@   r   r   machiner   rO   rP   r   join)
r   r   r   git_evpr_npr_evguard_evqc_evall_passfail_reasonss
             r%   
cmd_verifyr$    s   $,,E

 C
o,SE=qA"$F"("2E*h(.~(>E*n%)/)@E*o&  -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#$<= 	f$ 	&(Ov%  E<vx&,H	J45j,'1eT\\N">?@<<$**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=>r$   c                    t        | j                        }|d   dk7  rt        d|d    dd       d|d<   t        |dt	               	       d
|d   d   d<   t        |       t        | j                   d       y
)Nrk   r   u   approve 불가: 현재 상태=u    (GUARD_PASS 필요)r   Trn   r   )rj   r   rm   rf   approveu   : → HUMAN_APPROVED)r   rE   r   r   r@   r   r   r   s     r%   cmd_approver'    s    $,,E_-,U?-C,DDXY	
 #E
'vx812E*l#I.	%L234r$   c                    t        | j                        }t        |dt               dt	        | dd       i       t        |       t        | j                   d       y)Nr   r  r   u   : → CANCELLEDr   )r   rE   r   r@   getattrr   r   r   s     r%   
cmd_cancelr*    sO    $,,E{&(h =>@	%Lo./r$   c                    t        | j                        }t        |dt               d| j                  i       t        |       t        | j                   d| j                   d       y)Nr   r  r   u   : → FAILED (r   r   )r   rE   r   r@   r  r   r   r   s     r%   cmd_failr,    sS    $,,Exvx,.	%LnT[[M;<r$   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   )rE   rk   missingF)rK   r   z: state file missingr   ru   rv   ztask: rE   zstate: rk   ztransitions: rl   rm   zbranch: r_   zpr: r`   z
guard_sh: rc   zqc_report_guard: rd   zhuman_approved: rn   zbypass: ro   )r   rE   r  r   rO   rP   r   r7   )r   r   evs      r%   
cmd_statusr0    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)*+r$   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.Trr   z.tmp)dirsuffixwrV   rx   Fru   rv   N)parentrz   tempfilemkstempr:   r5   fdopenrO   dumpr~   r4   unlinkOSError)pathr   fdtmp_pathfs        r%   _atomic_writer@    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                
   | 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 파일이 있는지 확인하세요.ru   Nr   rm   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)
NTrr   previous_bottask/-failed)
rE   rD  new_botfrom_branch
new_branch
started_atts_filenametakeover_statusfailure_reasonfailure_check	takeover-rB   )rz   r7   r@  r4   )
r  rO  handoff_data_partialr/  evidence_dir_earlyrI  rH  rE   rL  ts_isos
       r%   _save_early_failurez)cmd_takeover.<locals>._save_early_failureC  s    	$$TD$A"!5!; @ @ P"* %gYay9$*#+"(!.B ,;-u/MMrR 		s   AA 	AAmemoryhandoffsrB   u   handoff 파일 없음: 1_handoff_existsr   T)rE   r_   check_head_shaworkspace_rootu   handoff 검증 실패: z; 2_validate_handoffu   handoff 검증 실패:
  r*   r   z--verifyzfrom-branch 'u   ' 존재하지 않음: 3_from_branch_existshead_shar   z
.worktreesrF  u#   새 worktree 경로 이미 존재: 5_worktree_path_collisionu/   새 worktree 경로가 이미 존재합니다: rE  u   새 branch 이미 존재: 6_branch_collisionu   새 branch 'u_   '가 이미 존재합니다. 다른 bot ID를 사용하거나 기존 branch를 삭제하세요.)r*   r   origin/mainu    origin/main HEAD 조회 실패: rP  c                    	 j                  d      
t              t        	      d| d}t        |       y # t        $ r Y y w xY w)NrD  rG  )rE   rD  rH  base_shar\  handoff_pathrI  rJ  new_worktree_pathrK  rL  rM  rN  )r7   r:   r@  r4   )r  r/  ra  evidence_filerI  handoff_datarb  rH  rJ  rc  recorded_headrE   rL  rS  s     r%   _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--forcer_   z-Du   start_task_guard.py 없음: z--task--botr   r
   r   u   start_task_guard 실패 (exit=z): r   rD  successr   )rE   rD  rH  ra  r\  rb  rI  rJ  rc  rK  rL  rM  start_guard_stdoutu   takeover 성공: z
  previous_bot=u    → new_bot=z
  new branch:   z
  new worktree: z
  evidence:     r   )r  r:   rO  r:   rQ  zdict | NonereturnNone)r  r:   rn  ro  )rE   rI  botr:   r;   r   r<  insertrB  ImportErrorr   r   r    r   r!   r"   r   r  r   r   r   r=   r7   r<   r8   r9   
executabler5   r6   r@  r   ) r   scripts_dirrB  r   now_utcrT  okerrors	err_linesr   proc_branch	proc_mainevidence_dirrg  proc_wtr  start_guard_script
proc_guardrm   ra  rR  rd  rI  re  rb  rH  rJ  rc  rf  rE   rL  rS  s                       @@@@@@@@@@@@@r%   cmd_takeoverr  *  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  0 	 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%, ',- .(/		+ O  
5cU ;VX	
 	

s   7T 	U "T;;U c                 H    t         j                  j                  dd      dk(  S )NTASKCTL_BYPASSr   1)r5   r6   r7   r#   r$   r%   _bypass_activer    s    ::>>*B/366r$   c           
        t        | j                        }t               }|r6dt               t	               d|d<   t        dt        j                         n|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       t        d| j                        }|d   |d	   d<   ||d	   d<   |d   dk7  r)d|d	   d
   d<   t        |       t        d|d    dd       t        | j                        }|d   |d	   d<   ||d	   d<   |d   dk7  r)d|d	   d
   d<   t        |       t        d|d    dd       |d	   j                  d      }|rt        |      }|d   |d	   d<   |d   |d	   d<   |j                  d      |d	   d<   |j                  d       |d	   d <   |j                  d      d!vrE|j                  d      4d|d	   d
   d<   t        |       t        d"|j                  d       d       t        |d         s(d|d	   d
   d<   t        |       t        d#|d    d       |d	   j                  d      }|s"d|d	   d
   d<   t        |       t        d$d       | j                  r~t               }||d	   d%<   d|d	   d&<   d'|d	   d
   d<   t!        |d(t	               d|d)|*       t!        |d+t	               |,       t        |       t#        | j                   d-| d       y't$        j&                  j                  d.d/      }t)        d0d1dt+        |      d2d3d4|gd5d6id78      }	|	j,                  |	j.                  d9d  |	j                  d9d  d:|d	   d;<   |	j,                  d'k7  rW|	j,                  |d	   d
   d<   t        |       t        d<|	j,                   d=|	j                  d>d   |	j,                  xs d       t               }||d	   d%<   d'|d	   d
   d<   t!        |d(t	               ||d?|*       t!        |d+t	               |,       t        |       t#        | j                   d@| dA       y')BNTrg   ro   u3   ★★★ TASKCTL BYPASS USED — Chairman overrider   rk   r   r   rm   rf   mergeu   merge 차단: 현재 상태=u*    (HUMAN_APPROVED 필요. 'taskctl approve u	   ' 먼저)r   u   merge 차단: state=CANCELLEDr  r   rc   guard_sh_detail_merger   u+   merge 차단: guard.sh pre-push FAIL (exit=r   r   rd   qc_report_guard_detail_mergeu)   merge 차단: qc_report_guard FAIL (exit=r`   ra   rb   r   r   >   N	MERGEABLEu   merge 차단: PR mergeable=u1   merge 차단: 8 required CI checks 미통과 — u7   merge 차단: PR 번호 없음 (taskctl pr-open 먼저)re   merge_dry_runr   r   )dry_runro   r   r   )rj   r   u)   : dry-run merge → MERGED → DONE (PR #GH_REPOzJeon-Jonghyuk/dev_workspacer   r   z--mergez--delete-branchz--repoTASKCTL_INVOKEDr  r   )r   r/   r   )r   r   r   merge_subprocessu   merge 실패: gh pr merge exit=z stderr=r   )r   ro   z: merged PR #u    → MERGED → DONE)r   rE   r  r&   r@   r   r   r   r   r   r  r  r7   r   r  r  r   r   r5   r6   r   r:   r   r<   )
r   r   ro   r   r!  r  r  merge_tsrepor   s
             r%   	cmd_merger  	  s&   $,,EF&X
h
 	C#**U !%5578E*l+G4%L.u_/E.F G<<@LL>T ![078E*l+G4%L0!4 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||6/7j+,-1j/*34j,'0E868%)V< 	" 	E6@eT\\N"KD6QRST ::>>)%BCD	tWc$i4ExQUV$D __{{45){{45)-E*()
 !37??j,'0e-doo-> ?kk$%()+OO q	

 vH+3E*'(/0E*l#G,xvx F3 vVXV<	%LmD61EFGr$   c                 B   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	                  t               |j                  dd
      } ||       |j                  ddd       |j	                  t               |j                  dd
      } ||       |j	                  t               |j                  dd 
      } ||       |j                  d!dd"       |j	                  t               |j                  d#d$
      } ||       |j                  d%d &       |j	                  t               |j                  d'd(
      } ||       |j                  d%d)       |j	                  t                |j                  d*d+
      } ||       |j                  ddd,       |j	                  t"               |j                  d-d.
      } ||       |j                  d/d0dd1d23       |j                  d4dd56       |j	                  t$               | S )7Nr   uI   task 상태 enforcement layer + main 진입 단일 경로 (task-2449 MVP))progdescriptioncommandT)destrequiredc                *    | j                  dd       y )NrE   u   task ID (예: task-2449)help)add_argument)sps    r%   _add_taskidz!build_parser.<locals>._add_taskid  s    
	(BCr$   initu   CREATED 상태 생성r  )funcdispatchu   DISPATCHED 전환acku   ACKED 전환 (봇 수신)r9   u   RUNNING 전환zpr-openu   PR_OPEN 전환z--pru	   PR 번호)typer  r  r  uO   evidence 자동 수집 + guard.sh + qc_report_guard 실행, PASS 시 GUARD_PASSz	--machine
store_trueu   state JSON 출력)actionr  r&  u%   HUMAN_APPROVED 전환 (회장 승인)r  u   main 진입 단일 경로z	--dry-runu,   actual gh pr merge skip — 상태만 전이cancelu   CANCELLED 전환z--reason)defaultfailu   FAILED 전환)r  r   u   현재 상태 + evidence 출력u   JSON 출력takeoveruQ   handoff evidence 기반 봇 인계 — 새 worktree + branch + start_guard 자동z--fromrI  BRANCHu/   이전 봇의 branch (예: task/task-2458-dev4))r  r  metavarr  rk  u   새 봇 ID (예: dev5))r  r  )argparseArgumentParseradd_subparsers
add_parserset_defaultsr   r   r   r   r  intr   r$  r'  r  r*  r,  r0  r  )r   subr  r  s       r%   build_parserr    s   _	A 

	D

9CD 
%<	=BOR__(_3	
)<	=BOR__,_7	$?	@BOR__'_2	$4	5BOR__'_2		(8	9BOOOFt+OFOOO%	^ 
 
`BOOOK;NOOOOO$		(O	PBOR__+_6	&A	BBOOOKG  I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&Hr$   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: ru   zinternal error: z: r   )
r  
parse_argsr  
SystemExitr8   TimeoutExpiredr   r4   r  __name__)argvparserr   rcr   s        r%   mainr    s    ^FT"D@YYt_ 7N  $$ .#C5)1-- @S	 2 232cU;Q??@s!   4 BA$$B0%BB__main__)rn  r:   )rE   r:   rn  r   )r   dict[str, Any]rn  r:   )rE   r:   rn  r  )r   r  rn  ro  )rE   r:   r   boolrn  dict[str, Any] | None)r   r  r   r:   rj   z
str | Noner   r  r   r  rn  ro  )r   )r   r:   r   r  rn  r   )r   r:   rn  ro  )
r   z	list[str]r0   zPath | Noner/   r  r   zdict[str, str] | Nonern  zsubprocess.CompletedProcess)r   argparse.Namespacern  r  r   )r   r  r   r:   r   r  rn  r  )rn  r  )r`   z
int | Nonern  r  )r  r:   rE   r:   rn  r  )rb   zdict[str, str]rn  r  )r<  r   r   r  rn  ro  )rn  r  )rn  zargparse.ArgumentParser)r  zlist[str] | Nonern  r  )C__doc__
__future__r   r  r2   rW   rO   r5   r8   r   r6  r   r   pathlibr   typingr   r   r	   r6   r7   r;   rC   r  r  r   __annotations__r   r   r   r   r&   r@   rF   rT   r[   rp   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r$  r'  r*  r,  r0  r@  r  r  r  r  r  r  r   r#   r$   r%   <module>r     s?  . #     	  
  '  * *  02GHI	 7*	y :-i'*>>	$ 	   ~)[{i(#Y/jhEe, (  < ;E()Z
N, 
 . 
 .	 M 
 M16 < LP.2#'+''(,'N
 04C&*	#	/J	" :>!6BE613 F	;:D<*Sv7@PEP zCHHTV r$   