
    #jL                       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Z ee      j'                         j(                  d   ZdZ ee      Zeev Zes ej4                  defdeef       ej6                  e      d	 ej8                         v s ej:                  e      r ej6                  e      nd	d
 ej8                         v s ej:                  e      r ej6                  e      nd
 ej6                  e      dz  Z ej>                  de d      dz   deiz  Z  e! ejD                  e             dxZxZZddZ#dddZ$dddZ%d Z&ddZ'd Z(d Z)d Z*d Z+d Z,y) uC  
task-2729+9 회귀 테스트: base source isolation (5 케이스)

모리건 (QA/회귀 테스트 엔지니어) — 2026-06-06

검증 대상:
  - cmd_create() 의 origin/main 기반 강제 (B1/B2 하드닝)
  - fail-closed 로직 (origin remote 존재 + origin/main 미해결)
  - 로컬 전용 repo 에서 HEAD 를 explicit SHA base 로 사용
  - 성공 마커 enriched 필드 전체 존재 검증
  - pre-push merge-base 분기 조건 단위 검증

모든 temp git repo 는 pytest tmp_path 하위에 생성.
canonical /home/jay/workspace 는 절대 건드리지 않는다.
    )annotationsN)Path   z	wt-2729p9)in)z0%(py1)s in %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
}str_WORKTREE_ROOT)py1py3py4py6u    잘못된 WORKTREE_ROOT 감지: uA   . canonical workspace 를 건드리지 않는지 확인하세요.z
>assert %(py8)spy8c                     t         j                  j                         } d| d<   d| d<   d| d<   d| d<   d| d<   d	| d
<   d| d<   d| d<   d| d<   | S )uT   canonical ~/.gitconfig, SSH 키 등 외부 영향을 차단한 격리 환경 반환.z	/dev/nullGIT_CONFIG_GLOBALzmorrigan-testerGIT_AUTHOR_NAMEzmorrigan@test.invalidGIT_AUTHOR_EMAILGIT_COMMITTER_NAMEGIT_COMMITTER_EMAILz/tmpHOME1GIT_CONFIG_COUNTzcommit.gpgsignGIT_CONFIG_KEY_0falseGIT_CONFIG_VALUE_0)osenvironcopyenvs    f/home/jay/workspace/.worktrees/task-2729+10-dev6/tests/regression/test_base_source_isolation_2729p9.py_git_envr    )   sx    
**//
C*C.C5C 1C!8CCK!C.C 'CJ    c                "   |xs
 t               }t        j                  dg| z   |dd|d      }|rG|j                  dk7  r8t	        ddj                  |        d|j                  j                                |j                  j                         S )	u*   git 명령 실행 → stdout strip 반환.gitT   )cwdcapture_outputtextr   timeoutr   zgit  z	 failed:
)	r    
subprocessrun
returncodeRuntimeErrorjoinstderrstripstdout)argsr%   r   checkers         r   _gitr6   9   s    xzA	$	A "T#((4.!1AHHNN<L;MNOO88>>r!   c                0   |xs
 t               }t        j                  j                  | |      }t	        |d      5 }|j                  d| d       ddd       t        d|g| |       t        ddd	d
|g| |       t        ddg| |      S # 1 sw Y   <xY w)u3   파일 하나 생성 후 커밋, 커밋 SHA 반환.wzcontent of 
Naddr%   r   z-czcommit.gpgsign=falsecommitz-m	rev-parseHEAD)r    r   pathr.   openwriter6   )repofilenamemessager   r4   fpathfs          r   _commitrG   I   s    xzAGGLLx(E	eS	 ,Q	+hZr*+,%	!,$&$	@dPQRf%4Q77	, ,s   BBc                 F   t        t        dz  dz        } t        j                  }|j                  } ||       }|st        j                  d|        dz   dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dt        j                         v st        j                  |       rt        j                  |       ndt        j                  |      dz  }t        t        j                  |            dx}x}}d	}|t        j                  v rt        j                  j                  |       t        t              t        j                  vr-t        j                  j                  d
t        t                     d}t         j"                  j%                  ||       }t         j"                  j'                  |      }|j(                  j+                  |       |S )uK   wt-2729p9 worktree 의 worktree_manager.py 를 importlib 로 직접 로드.scriptszworktree_manager.pyu   worktree_manager.py 없음: zd
>assert %(py7)s
{%(py7)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.path
}.exists
}(%(py5)s)
}r   	spec_path)py0py2r   py5py7Nz/home/jay/workspacer   worktree_manager_wt_2729p9)r   r   r   r?   exists
@pytest_ar_format_assertmsg@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationsysremoveinsert	importlibutilspec_from_file_locationmodule_from_specloaderexec_module)	rJ   @py_assert1@py_assert3@py_assert6@py_format8
_canonicalmod_namespecmods	            r   _load_worktree_managerrj   X   sL   NY.1FFGI77P7>>P>)$P$PP(DYK&PPPPPPP2PPP2PPP7PPP>PPPPPP)PPP)PPP$PPPPPP 'JSXX
#
>#((*3~./ ,H>>11(IFD
..
)
)$
/CKKC Jr!   c                   t               }t        | dz        }t        j                  |       t	        dddd|gt        |       |       t        | dz        }t	        d||gt        |       |       t	        g d	||       t        |d
d|      }t	        g d||       t        | dz        }t	        d||gt        |       |       t	        g d	||       |||fS )u   
    bare origin 을 만들고, seed 커밋으로 main 을 채운 뒤 clone 반환.

    Returns:
        (origin_dir, clone_dir, sha_fresh) — sha_fresh = origin/main tip SHA
    z
origin.gitinitz--bare-bmainr;   seedclonecheckoutz-Brn   zseed.txtzinitial commitr   pushoriginrn   )r    r   r   makedirsr6   rG   )tmp_pathr   
origin_dirseed_dir	sha_fresh	clone_dirs         r   _make_origin_cloner|   q   s     *CX,-JKK
&(D&*	53x=cR 8f$%H':x	(c(mE	#s;*.>CHI	#s; Hw&'I':y	)s8}#F	#<y)++r!   c                   t               }t               }t        |       \  }}}t        |dd|      }||k7  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      nddt        j                         v st	        j                  |      rt	        j                  |      nddz  }t	        j                  d	      d
z   d|iz  }	t        t	        j                  |	            d}t        ddg||      }
|
|k(  }|st	        j
                  d|fd|
|f      dt        j                         v st	        j                  |
      rt	        j                  |
      nddt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd|iz  }	t        t	        j                  |	            d}t        | dz        }|j                  |ddd|      }|d   }d}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	t	        j                  d|       dz   d|	iz  }t        t	        j                  |            dx}x}}|d    }d}||u }|st	        j
                  d!|fd"||f      t	        j                  |      t	        j                  |      dz  }	t	        j                  d#|       dz   d|	iz  }t        t	        j                  |            d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  }t	        j                  d'|d$    d(|       d)z   d*|iz  }t        t	        j                  |            dx}}|d+   }g }d}||u}|}|r&t         j"                  }|j$                  } ||      }|}|st	        j
                  d,|fd-||f      d.t        j                         v st	        j                  |      rt	        j                  |      nd.t	        j                  |      d/z  }d0d1|iz  }|j'                  |       |rd2d3t        j                         v st	        j                  t               rt	        j                  t               nd3t	        j                        t	        j                        d.t        j                         v st	        j                  |      rt	        j                  |      nd.t	        j                        d4z  }|j'                  |       t	        j(                  |d5      i z  }t	        j                  d6|       d7z   d8|iz  }t        t	        j                  |            dx}x}x}x}x}x}}t        ddg||      }||k(  }|st	        j
                  d|fd||f      d9t        j                         v st	        j                  |      rt	        j                  |      nd9dt        j                         v st	        j                  |      rt	        j                  |      nddz  }t	        j                  d:| d;| d<      d
z   d|iz  }	t        t	        j                  |	            d}|j+                  d=      }g }|}|r&t         j"                  }|j,                  } ||      }|}|sd>d?d@t        j                         v st	        j                  |      rt	        j                  |      nd@iz  }|j'                  |       |rdAd3t        j                         v st	        j                  t               rt	        j                  t               nd3t	        j                        t	        j                        d@t        j                         v st	        j                  |      rt	        j                  |      nd@t	        j                  |      dBz  } |j'                  |        t	        j(                  |d5      i z  }!t	        j                  dC|       dDz   dE|!iz  }"t        t	        j                  |"            dx}x}x}x}}t/        j0                  t3        |      j5                               }#|#dF   }dG}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	t	        j                  dH|#dF          dz   d|	iz  }t        t	        j                  |            d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  }t	        j                  dI|#d$    d(|       d)z   d*|iz  }t        t	        j                  |            dx}}y)Ju]  
    [시나리오] bare origin + clone.
    로컬 main 은 STALE (추가 커밋 있음), origin/main tracking ref = SHA_FRESH.
    HEAD 는 로컬 main.

    [기대]
    - cmd_create 반환: status=="created", base_fallback is False, base_sha == SHA_FRESH
    - 생성된 worktree HEAD == SHA_FRESH
    - marker: base_source == "origin/main"
    zlocal_only.txtzstale local commitr   !=z%(py0)s != %(py2)s	sha_stalerz   rK   rL   u   STALE != FRESH 전제
>assert %(py4)sr   Nr=   r>   r;   ==z%(py0)s == %(py2)sheadzassert %(py4)seventsz
task-test1qaFcopy_env
events_dirstatuscreatedz%(py1)s == %(py4)sr	   r      status 는 created 여야 함: 
>assert %(py6)sr   base_fallbackisz%(py1)s is %(py4)su$   base_fallback 은 False 여야 함: base_shaz%(py1)s == %(py3)sr	   r
   	base_sha= != sha_fresh=
>assert %(py5)srM   worktree_pathis notz%(py2)s is not %(py5)swt_pathrL   rM   %(py7)srN   a%(py16)s
{%(py16)s = %(py13)s
{%(py13)s = %(py11)s
{%(py11)s = %(py9)s.path
}.isdir
}(%(py14)s)
}r   py9py11py13py14py16r      worktree 미생성: 
>assert %(py19)spy19wt_headworktree HEAD=    가 origin/main tip=u"    와 다름 (stale base 사용됨)base_marker_path%(py2)srL   marker_path]%(py11)s
{%(py11)s = %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s.path
}.exists
}(%(py9)s)
}r   r   r   r   r   u   마커 파일 없음: 
>assert %(py14)sr   base_sourceorigin/mainu+   base_source 가 origin/main 이어야 함:    마커 base_sha=)rj   r    r|   rG   rQ   _call_reprcomparerS   rT   rU   rV   rR   rW   rX   r6   r   
cmd_creater   r?   isdirappend_format_boolopgetrP   jsonloadsr   	read_text)$rw   wmr   rx   r{   rz   r   rb   @py_format3@py_format5r   r   result@py_assert0rc   @py_assert2@py_format7@py_format4@py_format6r   @py_assert4@py_assert10@py_assert12@py_assert15re   @py_format17@py_format18@py_format20r   r   @py_assert5@py_assert7@py_format12@py_format13@py_format15markers$                                       r   (test_1_stale_local_main_uses_origin_baser      s1    
 	!B
*C'9('C$J	9 	#35IsSI	!:::9	::::::9:::9::::::	:::	::::#::::::: f%9#>D9494499X()J]]  F (TyTy(TTTyTTTTTTyTTT,KF8*TTTTTTTT/"\e\"e+\\\"e\\\"\\\e\\\/STZS[-\\\\\\\\* *            "+    "+    F:&'~i[A    
 _%G[$[7$[277[7==[=#9[#9[[[7$[[[[[[7[[[7[[[$[[[[[[[[[[2[[[2[[[7[[[=[[[[[[[[[[[[#9[[[[[[[[[=QRYQZ;[[[[[[[[[K(g3?Gi  7i                          	!6ykAcd    
 **/0K^;^;277^7>>^>+6^6^^^^^^;^^^;^^^^;^^^^^2^^^2^^^7^^^>^^^^^^+^^^+^^^6^^^^^^^^^:PQ\P]8^^^^^^^^ZZ[)3356F-  M  M1   M    !    %2    6f]6K5LM     * *            "+    "+    6*-.nYKH    r!   c           	     	   t               }t               }t        | dz        }t        j                  |       t        ddd|g||       t        |dd|       t        d	d
dt        | dz        g||       t        ddg||      }t        | dz        }|j                  |ddd|      }|d   }d}||k(  }	|	st        j                  d|	fd||f      t        j                  |      t        j                  |      dz  }
t        j                  d|       dz   d|
iz  }t        t        j                  |            dx}x}	}|j                  d      }d}	||	u }|st        j                  d|fd||	f      d t        j                          v st        j"                  |      rt        j                  |      nd t        j                  |	      d!z  }t        j                  d"|       d#z   d$|iz  }t        t        j                  |            dx}}	t%        |      d%z  }|d&z  }|j&                  } |       }| }|st        j                  d'|       d(z   d)t        j                          v st        j"                  |      rt        j                  |      nd)t        j                  |      t        j                  |      d*z  }t        t        j                  |            dx}x}}t%        |      d+z  }|j&                  } |       }|st        j                  d,|       d-z   d.t        j                          v st        j"                  |      rt        j                  |      nd.t        j                  |      t        j                  |      d*z  }
t        t        j                  |
            dx}}t)        j*                  |j-                               }|d/   }d0}||k(  }	|	st        j                  d|	fd||f      t        j                  |      t        j                  |      dz  }
t        j                  d1|d/          dz   d|
iz  }t        t        j                  |            dx}x}	}|d2   }d}||k(  }	|	slt        j                  d|	fd||f      t        j                  |      t        j                  |      dz  }
d3d|
iz  }t        t        j                  |            dx}x}	}y)4u|  
    [시나리오] repo 에 origin remote 설정됨(존재하지 않는 경로 OK).
    refs/remotes/origin/main 없음 (미 fetch).
    HEAD 는 로컬 main(SHA_STALE).

    [기대]
    - cmd_create 반환: status == "failed"
    - worktree 디렉토리 미생성
    - <events_dir>/<task_id>.worktree-base-failed.json 존재
    - reason == "STALE_BASE_ORIGIN_UNRESOLVED"
    localrl   rm   rn   r;   zinit.txtinitialr   remoter:   ru   znonexistent_origin.gitr=   r>   r   z
task-test2r   Fr   r   failedr   r   r   u4   status 는 failed 여야 함 (fail-closed). 실제: r   r   Nr   r   )z%(py0)s is %(py3)sr   rK   r
   u&   worktree_path 는 None 이어야 함: r   rM   z
.worktreesztask-test2-qau9   worktree 디렉터리가 생성됨 (fail-closed 위반): zG
>assert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}task_wt)rK   rL   r   z$task-test2.worktree-base-failed.jsonu   failed 마커 없음: zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}failed_markerreasonSTALE_BASE_ORIGIN_UNRESOLVEDu7   reason 이 STALE_BASE_ORIGIN_UNRESOLVED 이어야 함: task_idzassert %(py6)s)rj   r    r   r   rv   r6   rG   r   rQ   r   rV   rR   rW   rX   r   rS   rT   rU   r   rP   r   r   r   )rw   r   r   	local_dirr   r   r   r   rc   r   r   r   r   rb   r   r   wt_dirr   r   r   marker_datas                        r   -test_2_origin_exists_unresolvable_fail_closedr      s    
 	!B
*C Hw&'IKK	&$		*	sCIz9#6 		5(C3K(K$LM k6*	sCIX()J]]  F ( x x'  x         (    ?vhG    
 jj)GN7d?NNN7dNNNNNN7NNN7NNNdNNNDWINNNNNNN )_|+F&G~~f~ffff#\]d\e!fffffffwfffwfff~fffffffff $'MMMK!K!KK%;M?#KKKKKKK=KKK=KKKKKK!KKKKKK**]4467Kx  $B  $BB   $B    !    %C    B+hBWAXY     y!1\1!\1111!\111!111\1111111r!   c                f   t               }t               }t        | dz        }t        j                  |       t        ddd|g||       t        |dd|      }t        d	g||      }d
}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d|      dz   d|iz  }	t        t        j                  |	            dx}}t        | dz        }
|j!                  |ddd|
      }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|       dz   d|iz  }t        t        j                  |            dx}x}}|d   }d }||u }|st        j                  d!|fd"||f      t        j                  |      t        j                  |      dz  }t        j                  d#|       dz   d|iz  }t        t        j                  |            d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  }t        j                  d(|d$    d)|       dz   d|iz  }	t        t        j                  |	            dx}}|d*   }g }d}||u}|}|r&t        j"                  }|j$                  } ||      }|}|st        j                  d+|fd,||f      d-t        j                         v st        j                  |      rt        j                  |      nd-t        j                  |      d.z  }	d/d0|	iz  }|j'                  |       |rd1d2t        j                         v st        j                  t              rt        j                  t              nd2t        j                        t        j                        d-t        j                         v st        j                  |      rt        j                  |      nd-t        j                        d3z  }|j'                  |       t        j(                  |d4      i z  }t        j                  d5|       d6z   d7|iz  }t        t        j                  |            dx}x}x}x}x}x}}t        d8d9g||      }||k(  }|st        j                  d|fd:||f      d;t        j                         v st        j                  |      rt        j                  |      nd;d&t        j                         v st        j                  |      rt        j                  |      nd&d<z  }t        j                  d=| d)|       d>z   d?|iz  }t        t        j                  |            d}|j+                  d@      }g }|}|r&t        j"                  }|j,                  } ||      }|}|sdAdBdCt        j                         v st        j                  |      rt        j                  |      ndCiz  }|j'                  |       |rdDd2t        j                         v st        j                  t              rt        j                  t              nd2t        j                        t        j                        dCt        j                         v st        j                  |      rt        j                  |      ndCt        j                  |      dEz  }|j'                  |       t        j(                  |d4      i z  }t        j                  dF|       dGz   dH|iz  } t        t        j                  |             dx}x}x}x}}t/        j0                  t3        |      j5                               }!|!dI   }dJ}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  dK|!dI   dL      dz   d|iz  }t        t        j                  |            d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  }t        j                  dM|!d$    d)|       dz   d|iz  }	t        t        j                  |	            dx}}y)Nu  
    [시나리오] origin remote 없는 로컬 전용 repo.
    커밋 1개 이상. HEAD = SHA_LOCAL.

    [기대]
    - status == "created"
    - worktree 생성됨
    - base_source == "local_head_no_origin"
    - base_sha == SHA_LOCAL
    - worktree HEAD == SHA_LOCAL
    - base_fallback is True  (로컬 HEAD fallback 임을 명시)

    회귀 방지: origin 없는 repo 가 fail-closed 되지 않음을 검증.
    
local_onlyrl   rm   rn   r;   zfile.txtzonly commitr   r    r   )z%(py0)s == %(py3)sremotesr   u!   remote 가 존재해선 안 됨: r   rM   Nr   z
task-test3r   Fr   r   r   r   r   uE   origin 없는 로컬 repo 에서 fail-closed 되면 안 됨. 실제: r   r   r   Tr   r   u=   base_fallback 은 True 이어야 함 (local_head_no_origin): r   r   	sha_localr   r   z != sha_local=r   r   r   r   r   r   rN   r   r   r   r   r   r   r   r=   r>   r   r   r   r   r   r   r   r   rL   r   r   r      마커 없음: r   r   r   local_head_no_originbase_source=z != 'local_head_no_origin'r   )rj   r    r   r   rv   r6   rG   rQ   r   rS   rT   rU   rV   rR   rW   rX   r   r?   r   r   r   r   rP   r   r   r   r   )"rw   r   r   r   r   r   r   rb   r   r   r   r   r   rc   r   r   r   r   r   r   r   re   r   r   r   r   r   r   r   r   r   r   r   r   s"                                     r   )test_3_no_origin_local_head_explicit_baser     s'    
 	!B
*CH|+,IKK	&$		*	sC	:}#FI H:9#6GI7b=III7bIIIIII7III7IIIbIII=g[IIIIIIIX()J]]  F ( y y(  y         )    PPVxX     /" d "d*  "d    #    '+    HxP     * *            "+    "+    F:&'~i[A     _%G[$[7$[277[7==[=#9[#9[[[7$[[[[[[7[[[7[[[$[[[[[[[[[[2[[[2[[[7[[[=[[[[[[[[[[[[#9[[[[[[[[[=QRYQZ;[[[[[[[[[K(g3?Gi  7i                          		{;    
 **/0KW;W;277W7>>W>+6W6WWWWWW;WWW;WWWW;WWWWW2WWW2WWW7WWW>WWWWWW+WWW+WWW6WWWWWWWWW/+8WWWWWWWWZZ[)3356F-  $:  $::   $:    !    %;    vm,//IJ     * *            "+    "+    6*-.nYKH    r!   c                   t               }t               }t        |       \  }}}t        | dz        }|j	                  |ddd|      }|d   }d}	||	k(  }
|
st        j                  d|
fd	||	f      t        j                  |      t        j                  |	      d
z  }t        j                  d|       dz   d|iz  }t        t        j                  |            dx}x}
}	|j                  d      }g }|}|r&t        j                  }|j                  } ||      }|}|sdddt        j                          v st        j"                  |      rt        j                  |      ndiz  }|j%                  |       |rddt        j                          v st        j"                  t              rt        j                  t              ndt        j                        t        j                        dt        j                          v st        j"                  |      rt        j                  |      ndt        j                        dz  }|j%                  |       t        j&                  |d      i z  }t        j                  d|       dz   d|iz  }t        t        j                  |            dx}x}x}x}}t)        j*                  t-        |      j/                               }g d}|D cg c]	  }||vs| }}| }|st        j                  d| d|       dz   ddt        j                          v st        j"                  |      rt        j                  |      ndiz  }t        t        j                  |            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  }t        j                  d$|d     d%|       d&z   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  }t        j                  d)|d(    d%|       d&z   d'|iz  }t        t        j                  |            dx}}
|d*   }d+}	||	k(  }
|
st        j                  d|
fd	||	f      t        j                  |      t        j                  |	      d
z  }t        j                  d,|d*   d-      dz   d|iz  }t        t        j                  |            dx}x}
}	|d.   }d}	||	u}
|
st        j                  d/|
fd0||	f      t        j                  |      t        j                  |	      d
z  }t        j                  d1      dz   d|iz  }t        t        j                  |            dx}x}
}	g }|d2   }	t1        |	t              }|}|r|d2   }t3        |      }d3}||k\  } | }|sd4d5t        j                          v st        j"                  t0              rt        j                  t0              nd5t        j                  |	      d6t        j                          v st        j"                  t              rt        j                  t              nd6t        j                  |      d7z  }!|j%                  |!       |rt        j                  d8 fd9f      d:t        j                          v st        j"                  t2              rt        j                  t2              nd:t        j                  |      t        j                  |      t        j                  |      d;z  }"d<d=|"iz  }#|j%                  |#       t        j&                  |d      i z  }$t        j                  d>|d2         d?z   d@|$iz  }%t        t        j                  |%            dx}x}x}	x}x}x}x} }yc c}w )Au<  
    [시나리오] test_1 과 유사한 정상(origin/main 해결) 구성.

    [기대]
    성공 마커 JSON 에 다음 키가 **모두** 존재:
        base_source, base_sha, merge_base, origin_main_sha, canonical_head_sha
    값 검증:
        origin_main_sha == SHA_FRESH
        base_sha == SHA_FRESH
    r   z
task-test4r   Fr   r   r   r   r   r   r   r   r   Nr   r   rL   r   r   r   r   r   r   r   r   )r   r   
merge_baseorigin_main_shacanonical_head_shau    마커에 다음 키가 없음: u   . 마커 내용: z
>assert not %(py0)srK   missingr   r   rz   r   zorigin_main_sha=r   r   rM   r   r   r   r   r   z != 'origin/main'r   r   )z%(py1)s is not %(py4)su?   merge_base 가 None — 정상 경로에서 계산되어야 함r      z.%(py7)s
{%(py7)s = %(py2)s(%(py4)s, %(py5)s)
}
isinstancer   )rL   r   rM   rN   )>=)z4%(py13)s
{%(py13)s = %(py9)s(%(py11)s)
} >= %(py16)slen)r   r   r   r   z%(py18)spy18u1   canonical_head_sha 가 유효한 SHA 가 아님: z
>assert %(py21)spy21)rj   r    r|   r   r   rQ   r   rV   rR   rW   rX   r   r   r?   rP   rS   rT   rU   r   r   r   r   r   r   r   r   )&rw   r   r   rx   r{   rz   r   r   r   rc   r   r   r   r   rb   r   r   r   r   r   r   r   r   required_keyskr   @py_format2r   r   rd   r   r   @py_assert14re   r   @py_format19r   @py_format22s&                                         r   %test_4_success_marker_enriched_fieldsr  Y  s    
 	!B
*C'9('C$J	9X()J]]  F (TyTy(TTTyTTTTTTyTTT,KF8*TTTTTTTT**/0KW;W;277W7>>W>+6W6WWWWWW;WWW;WWWW;WWWWW2WWW2WWW7WWW>WWWWWW+WWW+WWW6WWWWWWWWW/+8WWWWWWWWZZ[)3356F gM';Q1F?q;G;; ;   +7)3DVHM              
 #$ $	1  $	    %      )2    )2    6"345^I;O     * *            "+    "+    F:&'~i[A     -  M  M1   M    !    %2    vm,//@A     , t t+  t         (,    	J    f12 :2C8 8 8H\A] SA]=^ bc =^bc=c              3      58    58    9    9  =^bc      >A    >A    B^    >_    cd        <FCW<X;[\      ) <s   -	a87a8c                	   t               }t        |       \  }}}t        | dz        }t        d||gt        |       |       t        g d||       t	        |dd|      }t        g d||       t        d	d
g||       t        ddg||      }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }	t        j                  d      dz   d|	iz  }
t        t        j                  |
            d}d}t        dd||g||       t	        |dd|       t        g d||      }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }	t        j                  d| d| d      dz   d|	iz  }
t        t        j                  |
            d}t        dd g||       t        d!d"|g||       d#}t        dd||g||       t	        |d$d%|       t        g d||      }||k7  }|st        j                  d&|fd'||f      d(t        j                         v st        j                  |      rt        j                  |      nd(dt        j                         v st        j                  |      rt        j                  |      nddz  }	t        j                  d)| d| d*      dz   d|	iz  }
t        t        j                  |
            d}||k(  }|st        j                  d|fd||f      d(t        j                         v st        j                  |      rt        j                  |      nd(d+t        j                         v st        j                  |      rt        j                  |      nd+dz  }	t        j                  d)| d,| d-      dz   d|	iz  }
t        t        j                  |
            d}y).u  
    pre-push scope_check 의 merge-base 기반 stale/fresh 분기 로직 단위 검증.

    pre-push 훅 자체를 직접 실행하지 않는 이유:
        pre-push 는 lock 파일, taskctl, scope_check, cancelled marker 등
        다단계 선행 검증을 요구하며, 이 검증들은 temp repo 에 준비하기 위한
        setup 비용이 매우 크고 canonical workspace 의 스크립트(taskctl.py 등)에
        의존한다. canonical 무손상 원칙 상 그 의존성을 temp repo 로 완전히 격리하기가
        불가능하므로, 핵심 분기 조건(merge-base 비교)만 git 명령 레벨에서 검증한다.

    (a) fresh 케이스: HEAD 가 origin/main tip 의 후손
        → merge-base == origin/main tip (FRESH 판정 조건 성립)

    (b) stale 케이스: origin/main 과 분기된(공통 조상이 origin/main tip 이 아닌) 브랜치
        → merge-base != origin/main tip (STALE 판정 조건 성립)
    seed2rp   r;   rq   z	fresh.txtzfresh origin commitr   rs   fetchru   r=   r   r   r   r   rz   r   u   origin/main tip 확인r   r   Nztask/task-test5-fresh-qarr   rm   zwork_fresh.txtzwork on fresh branch)z
merge-baser   r>   merge_base_freshz[FRESH] merge-base=r   u    과 달라야 함이 아님.
pre-push scope_check: merge-base == origin/main → three-dot diff (오탐 제거) 조건 성립해야 함.rn   resetz--hardztask/task-test5-stale-qazwork_stale.txtzwork on stale branchr~   r   merge_base_stalez[STALE] merge-base=uv    와 같으면 안 됨.
pre-push scope_check: merge-base != origin/main → STALE_BASE 차단 조건 성립해야 함.sha_origin_initialu    는 stale base=u    여야 함)r    r|   r   r6   rG   rQ   r   rS   rT   rU   rV   rR   rW   rX   )rw   r   rx   r{   r
  	seed2_dirrz   r   rb   r   r   fresh_branchr  stale_branchr	  s                  r   (test_5_prepush_merge_base_fresh_vs_staler    s-   " *C 1C80L-J	- Hw&'I':y	)s8}#F	#<	;0E3OI	#< 	'8	)5K7YCPOi'AAA?iAAAAAA?AAA?AAAAAAiAAAiAAAA)AAAAAAA .L	T<9 I')?SI-
 .                   /     /    .//D_DU Vv 	w     	*f	9#6'8/	0iSI-L	T<);<
 I')?SI-
 .                   /     /    .//D_DU Vi 	j     11  1                 2     2    .//?@R?SS^_    r!   )returndict)NT)
r2   z	list[str]r%   r   r   dict | Noner3   boolr  r   )N)
rB   r   rC   r   rD   r   r   r  r  r   )rw   r   r  ztuple[str, str, str])-__doc__
__future__r   builtinsrS   _pytest.assertion.rewrite	assertionrewriterQ   importlib.utilr\   r   r   r*   rY   pathlibr   pytest__file__resolveparentsr   r   r   r   r   r   rV   rT   rU   r   rR   @py_format9rW   rX   r    r6   rG   rj   r|   r   r   r   r  r   r!   r   <module>r!     sZ   #      	  
  
 h'')11!4 c.) {))  {)               )   )   *    '~&6 7F F      82,>8~=2H?L8~Wr!   