
    i                       d Z ddlmZ ddlZddlmc 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mZ ddlmZ ddlZ ee      j+                         j,                  d   ZddZ ej2                         dd       Zdd	Zdd
Zej:                  j=                  dg d      	 	 	 	 	 	 dd       ZddZ ddZ!ddZ"ddZ#ddZ$y)u  tests/regression/test_finish_task_routing.py — task-2471+1 자동화 회귀.

회장 명령 (A): ``finish-task`` 자동화 경로 — state machine 라우팅 검증.

dry-run 모드에서 현재 state별 다음 액션 라우팅을 검증한다 (실제 gh / git 호출
불필요). 잘못된 routing / no_route 상태에서 fail-closed (exit 1) 검증.

검증 routing:
- COMMITTED → pr-open
- PR_OPEN → ci-check
- CI_PENDING → gemini-evidence
- GEMINI_PENDING → review-ready
- REVIEW_READY → verify
- VERIFIED → approve
- HUMAN_APPROVED → merge
- MERGED → done
- DONE → halt (steps_taken=0, no action)
- terminal non-DONE (FAILED/CANCELLED) → halt fail
    )annotationsN)Path)Any   c                   | j                  dt        |             t        j                  j	                  dt        t
        dz  dz              }g }|}|r|j                  }|}|sdddt        j                         v st        j                  |      rt        j                  |      ndiz  }|j                  |       |rlddt        j                         v st        j                  |      rt        j                  |      ndt        j                        d	z  }|j                  |       t        j                  |d
      i z  }dd|iz  }	t        t        j                  |	            d x}x}}t        j                  j!                  |      }
|
t"        j$                  |j&                  <   |j                  j)                  |
       |
S )NWORKSPACE_ROOTtaskctl_isolated_finishscriptsz
taskctl.pyz%(py2)spy2specz#%(py6)s
{%(py6)s = %(py4)s.loader
})py4py6r   assert %(py9)spy9)setenvstr	importlibutilspec_from_file_location	WORKSPACEloader@py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprappend_format_boolopAssertionError_format_explanationmodule_from_specsysmodulesnameexec_module)monkeypatchrootr   @py_assert1@py_assert0@py_assert5@py_format3@py_format7@py_format8@py_format10mods              \/home/jay/workspace/.worktrees/task-2471+1-dev2/tests/regression/test_finish_task_routing.py_load_taskctlr1   #   s   'T3>>11!I	!L01D  44DKKK444DDK
..
)
)$
/C CKK		KKC J    c                    | dz  dz  }| dz  dz  }| dz  dz  }| dz  dz  }||||fD ]  }|j                  dd        t        ||       }| |||d	S )
Nz.tasksstateevidencememoryeventszorchestration-auditT)parentsexist_ok)tmp_pathr/   	state_dir
events_dir)mkdirr1   )r:   r&   r;   evidence_dirr<   	audit_dirdr/   s           r0   isolatedrA   0   s    8#g-Ih&3LH$x/J8#&;;Iz9= -	t,-
X
.C 	 r2   c                <   ||g d g ddd i d d d i d
ddd d ddd d d d dd}t        j                  |ddd	
      }t        j                  |j	                  d            j                         |d<   | | dz  j                  t        j                  |dd      d       y )Nztask/x-dev0   )
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)rN   rO   rP   reasonaudit_log_offset)task_idcurrent_statetransitionsr5   human_approvedbypassadmin_overrideT),:)ensure_ascii	sort_keys
separatorszutf-8	_checksumz.jsonr   )r[   indent)encoding)jsondumpshashlibsha256encode	hexdigest
write_text)r;   rS   rT   payload	canonicals        r0   _write_staterj   A   s    & ##&*#
   t< $
%G4 

et
I #>>)*:*:7*CDNNPGKG9E""..

7q9G / r2   c                r    t        j                  | |j                  dd      |j                  dd            S )Ndry_runT	max_steps   )rS   rl   rm   )argparse	Namespaceget)rS   kws     r0   _nsrs   e   s4    y$'&&b) r2   zsrc_state,expected_action))	COMMITTEDzpr-open)PR_OPENzci-check)
CI_PENDINGzgemini-evidence)GEMINI_PENDINGzreview-ready)REVIEW_READYverify)VERIFIEDapprove)HUMAN_APPROVEDmerge)MERGEDdonec                N	   d|j                          }t        | d   ||       | d   j                  t        |d             |j	                         j
                  }t        j                         }d}g }|t        |      k  ro||d  j                         }	|	snY|t        ||d        t        |	      z
  z  }|j                  ||d        \  }
}|j                  |
       ||z  }|t        |      k  ro|s{t        j                  d      dz   d	d
t        j                         v st        j                   |      rt        j"                  |      nd
iz  }t%        t        j&                  |            |d   }|j(                  }d} ||      }|st        j                  d| d|       dz   dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      t        j"                  |      dz  }t%        t        j&                  |            d x}x}}|d   d   }|j(                  }d} ||      }d}||u }|st        j*                  d|fd||f      dt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |      t        j"                  |      t        j"                  |      t        j"                  |      dz  }dd|iz  }t%        t        j&                  |            d x}x}x}x}}|d   }||k(  }|st        j*                  d|fd||f      t        j"                  |      dt        j                         v st        j                   |      rt        j"                  |      nddz  }dd|iz  }t%        t        j&                  |            d x}}|d    }||k(  }|st        j*                  d|fd||f      t        j"                  |      d!t        j                         v st        j                   |      rt        j"                  |      nd!dz  }dd|iz  }t%        t        j&                  |            d x}}y )"Nztask-finish-r;   r/   Trl   r   z#no JSON output from cmd_finish_taskz
>assert %(py0)spy0objslogzempty log for state=z: zG
>assert %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
}rec)r   r   r   r   rl   is)zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} is %(py9)sfirst)r   r   r   r   r   zassert %(py11)spy11r4   ==z%(py1)s == %(py3)s	src_statepy1py3assert %(py5)spy5actionexpected_action)lowerrj   cmd_finish_taskrs   
readouterroutra   JSONDecoderlenlstrip
raw_decoder   r   _format_assertmsgr   r   r   r   r   r    rq   _call_reprcompare)rA   capsysr   r   rS   r   decoderidxr   s_stripobjend@py_format1r   r(   @py_assert3r*   r,   r   @py_assert8@py_assert7r.   @py_format12r)   @py_assert2@py_format4@py_format6s                              r0   5test_finish_task_dryrun_routes_to_correct_next_actionr   m   s     Y__./0G+&;UO##C$>?




!
!C  G
CD
C.cd)""$s3st9~G,,%%c#$i0SCs
 C. 6666666664666466666
r(C77D5D75>D>DD1)BseDDDDDDD3DDD3DDD7DDD5DDD>DDDDDDJqME99'Y'9Y'4'4''''4''''''5'''5'''9'''Y''''''4'''''''>&>Y&&&&>Y&&&>&&&&&&Y&&&Y&&&&&&&?-?o----?o---?------o---o-------r2   c                j   d}t        | d   |d       | d   | dz  j                  d       | d   j                  t        |d	             |j	                         j
                  }t        j                         }d
}g }|t        |      k  rK||   dk7  r|dz  }	 |j                  ||d       \  }}|j                  |       ||z  }|t        |      k  rKt        |      }	d}
|	|
k\  }|st        j                  d|fd|	|
f      dt        j                         v st        j                   t              rt        j"                  t              nddt        j                         v st        j                   |      rt        j"                  |      ndt        j"                  |	      t        j"                  |
      dz  }dd|iz  }t%        t        j&                  |            dx}	x}}
|d   }|d   }||k(  }	|	st        j                  d|	fd||f      t        j"                  |      dt        j                         v st        j                   |      rt        j"                  |      nddz  }dd|iz  }t%        t        j&                  |            dx}}	|d   }d}||k(  }	|	slt        j                  d|	fd||f      t        j"                  |      t        j"                  |      dz  }dd |iz  }t%        t        j&                  |            dx}x}	}y# t        j                  $ r	 |dz  }Y w xY w)!uE   이미 DONE이면 추가 액션 없이 verify-consistency 후 종료.ztask-finish-already-doner;   DONEr<   z.donez{}r/   Fr   r   {rC   N)>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)sr   r   )r   r   r   r   zassert %(py8)spy8r   rS   r   r   r   r   r   final_statez%(py1)s == %(py4)sr   r   assert %(py6)sr   )rj   rg   r   rs   r   r   ra   r   r   r   JSONDecodeErrorr   r   r   r   r   r   r   r   r    )rA   r   rS   r   r   r   r   r   r   r   r*   @py_assert4r,   @py_format9finalr)   r   r   r   @py_format5s                       r0   ,test_finish_task_done_already_short_circuitsr      sM   (G+&8l	//;;DAUO##C$?@




!
!C G
CD
C.s8s?1HC	))#cd)4HC 	Cs
 C. t99>933tt9HE&w&&&&w&&&&&&&&&w&&&w&&&&&&&)6)6))))6))))))6))))))) ## 	1HC	s   L L21L2c                   d}t        | d   |d       | d   j                  t        |d            }d}||k(  }|st        j                  d|fd	||f      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}|j                         j                  }t        j                  |      }	|	d   }
d}|
|u }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}|	d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}y)u    FAILED 상태 → halt + exit 1.ztask-finish-failedr;   FAILEDr/   Fr   rC   r   z%(py0)s == %(py3)srcr   r   r   r   Nokr   z%(py1)s is %(py4)sr   r   r   r   r   rj   r   rs   r   r   r   r   r   r   r   r    r   r   ra   loadsrA   r   rS   r   r   r(   r   r   r   r   r)   r   r   r,   s                 r0   'test_finish_task_terminal_failed_blocksr      s5   "G+&:	%	(	(We)D	EBN27NNN2NNNNNN2NNN2NNNNNNNNNN




!
!C
**S/Ct9999})))))))))))))))))))r2   c                   d}t        | d   |d       | d   j                  t        |d            }d}||k(  }|st        j                  d|fd	||f      d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}|j                         j                  }t        j                  |      }	|	d   }
d}|
|u }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}d}
|	d   }|
|v }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}y)u>   라우팅 불가능한 state (예: BLOCKED) → halt + exit 1.ztask-finish-blockedr;   BLOCKEDr/   Fr   rC   r   r   r   r   r   r   Nr   r   r   r   r   r   zno automation routerQ   in)z%(py1)s in %(py4)sr   r   s                 r0    test_finish_task_no_route_blocksr      s4   #G+&;	%	(	(We)D	EBN27NNN2NNNNNN2NNN2NNNNNNNNNN




!
!C
**S/Ct9999 1CM1 M1111 M111 111M1111111r2   c                   d}t        | d   |d       | d   j                  t        |dd            }d}||v }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)uF   max_steps=0 가드는 정수로 강제되며 1 이상 (안전 가드).ztask-finish-guardr;   rt   r/   Tr   )rl   rm   )r   rC   r   )z%(py0)s in %(py3)sr   r   r   r   N)rj   r   rs   r   r   r   r   r   r   r   r    )rA   rS   r   r   r(   r   r   s          r0    test_finish_task_max_steps_guardr      s    !G+&=	%	(	(GTQ/
B
 2<222r2   c                v   d}t        j                  t              5 }| d   j                  t	        |d             ddd       j
                  }|j                  }d}||k(  }|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}x}x}}y# 1 sw Y   xY w)u#   state 파일 없으면 즉시 fail.ztask-finish-no-stater/   Fr   NrC   r   )zG%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.value
}.code
} == %(py7)sexcinfo)r   r   r   py7r   r   )pytestraises
SystemExitr   rs   valuecoder   r   r   r   r   r   r   r    )	rA   rS   r   r(   r   @py_assert6r*   r-   r.   s	            r0   %test_finish_task_state_missing_blocksr      s    $G	z	" Eg''GU(CDE=="=""""""""""""7"""7"""="""""""""""""E Es    D//D8)r&   pytest.MonkeyPatchr'   r   )r:   r   r&   r   )r;   r   rS   r   rT   r   returnNone)rS   r   r   zargparse.Namespace)r   r   r   r   r   r   )r   r   )%__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   ro   rc   importlib.utilr   ra   r"   pathlibr   typingr   r   __file__resolver8   r   r1   fixturerA   rj   rs   markparametrizer   r   r   r   r   r    r2   r0   <module>r      s   & #       
   N""$,,Q/	
   !H 	.!$.7:.	..:*6	*	2
#r2   