
    3j'                    r   U d Z ddlm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 dZded	<   d
Zded<   dZded<   dZded<   dZded<   dZded<   dZded<    G d de      Zd*dZd+dZddd,dZd-dZd.d Zd/d!Zd"d#	 	 	 	 	 	 	 d0d$Zd*d%Z	 	 	 	 	 	 	 	 d1d&Zeed'	 	 	 	 	 	 	 	 	 	 	 d2d(Z g d)Z!y)3u  anu_v3.branch_ref_allocator — task-2553+9 collision-safe branch name
allocator (회장 §4-1~4-4 / 9-R.3 / 9-R.4 / 9-R.6).

근본원인: live 메인 워크스페이스가 ``task/task-2553p1-f1-clean-replacement``
에 checkout 돼 있고, activation runner 의 ``git checkout -B <branch> <base>``
가 그 **live-checked-out branch ref 를 reset** → task-2553+8 DEFENSIVE_HOLD.

본 모듈 = 충돌하지 않는 **고유 신규 replacement branch name 을 할당**.
충돌은 강제 reset 이 아니라 **회피(새 name)** 로만 해소한다 (회장 §3).

설계 불변식:
  - **read-only**: ``git worktree list`` / ``git show-ref`` / ``git ls-remote``
    만 호출. branch 생성·reset·checkout·push·prune **부재**(정적·런타임).
  - **loop-until-clean (9-R.3)**: 단발 uuid 확률 방어 금지. candidate 가
    (worktree checked-out ∪ local refs ∪ remote refs) 3-source 전부에서
    absent 될 때까지 반복. bounded ``max_attempts``(기본 8) 초과 → HOLD.
  - **강제 reset 0 (회장 §3)**: 어떤 경우에도 기존 ref 를 reset/삭제 않음.
  - **9-R.6 audit trail**: 결과 provenance 는 ``schemas/
    branch_allocation_provenance.schema.json`` 와 1:1 (base_sha single
    authority — base_name 미기록).
    )annotationsN)datetimetimezone)Path)CallableFinalzanu_v3.branch_ref_allocatorz
Final[str]ALLOCATOR_MODULEz1.0.0ALLOCATOR_VERSIONz&anu_v3.branch_allocation_provenance.v1PROVENANCE_SCHEMA	ALLOCATEDSTATUS_ALLOCATEDHOLD_FOR_CHAIRSTATUS_HOLD   z
Final[int]DEFAULT_MAX_ATTEMPTS)worktreeshow-ref	ls-remote	rev-parsezFinal[tuple[str, ...]]READ_ONLY_GIT_VERBSc                      e Zd ZdZy)BranchAllocatorErroru>   allocation 실패. fail-closed: branch mutation 절대 부재.N)__name__
__module____qualname____doc__     2/home/jay/workspace/anu_v3/branch_ref_allocator.pyr   r   2   s    Hr   r   c                 f    t        j                  t        j                        j	                  d      S )Nz%Y-%m-%dT%H:%M:%SZ)r   nowr   utcstrftimer   r   r   _now_utcr$   6   s!    <<%../CDDr   c                 t    t         j                  j                         } dD ]  }| j                  |d        | S )uF   9-R.2 동일 패턴 — GIT_* 오염 변수 제거 (isolation 강제).)GIT_DIRGIT_WORK_TREEGIT_INDEX_FILEGIT_OBJECT_DIRECTORYGIT_COMMON_DIRN)osenvironcopypop)eks     r   _sanitized_envr1   :   s9    


A  	
a Hr   <   )timeoutc          	     .   |r|d   t         vrt        d|dd dt          d      t        t        |       j	                               }t        j                  dd|g|d	d	|d
t                     }|j                  |j                  j                         fS )u   absolute ``git -C <target>`` **read-only** 전용. (rc, stdout) 반환.

    호출 verb 가 READ_ONLY_GIT_VERBS 화이트리스트 밖이면 즉시 거부
    (런타임 fail-closed — mutating git 호출 경로 부재 강제).
    r   u.   read-only git verb 화이트리스트 위반: N   z
 (allowed=)gitz-CTF)capture_outputtextr3   checkenv)r   r   strr   resolve
subprocessrunr1   
returncodestdoutstrip)targetr3   argsabspathprocs        r   _git_rorG   H   s     47"55"<T"1XL I+,A/
 	
 $v,&&()G>>	g%%D ??DKK--///r   c                   t        | ddd      \  }}|dk7  rt        d|       i }d}|j                         D ]  }|j                  d      r|t	        d      d j                         }1|j                  d      sC|F|t	        d      d j                         }|j                  d	      st|||t	        d	      d <    |S )
u   ``git worktree list --porcelain`` → {branch_name: worktree_path}.

    모든 worktree(live 포함) 의 checked-out branch ref 를 파싱한다.
    r   listz--porcelainr   zworktree list rc=Nz	worktree zbranch refs/heads/)rG   r   
splitlines
startswithlenrB   )	repo_pathrcoutmappingcur_wtlinerefs          r   list_checked_out_branchesrU   b   s    
 iV]CGB	Qw"%6rd#;<< GF  ;??;'#k*+,224F__Y'F,>s9~'--/C~~m,4:C./01; Nr   c                B    t        | ddd      \  }}|dk7  s|r|dk(  ry|S )u   live(메인) workspace 가 현재 checkout 한 branch (detached → None).

    이 branch ref 는 회장 §3 에 따라 **절대 reset 하지 않는다** (식별 전용).
    r   z--abbrev-refHEADr   NrG   )rN   rO   rP   s      r   live_checkout_branchrY   v   s/    
 infEGB	QwcSF]Jr   c                6    t        | dddd|       \  }}|dk(  S )z@``git show-ref --verify --quiet refs/heads/<name>`` (read-only).r   z--verifyz--quietrJ   r   rX   )rN   namerO   _s       r   local_ref_existsr]      s-    :z9D66JEB 7Nr   origin)remotec               d    t        | dd||      \  }}|dk7  ryt        |j                               S )uD   ``git ls-remote --heads origin <name>`` 비어있지 않으면 True.r   z--headsr   T)rG   boolrB   )rN   r[   r_   rO   rP   s        r   remote_ref_existsrb      s7     iiFGB	Qw 		r   c                 D    t        j                         j                  dd S )zuuid4 hex 12 (9-R.3 suffix).N   )uuiduuid4hexr   r   r   
_new_runidrh      s    ::<CR  r   c                :    ||v t        | |      t        | |      dS )uH   candidate 의 3-source 점유 여부 (read-only). True = 점유(충돌).r   localr_   )r]   rb   )rN   	candidatechecked_outs      r   _probern      s*     ,!)Y7#Iy9 r   )max_attemptsrunid_factoryc                  t        |       }t        |       }t        | ||      }t        |j	                               }d}	d}
|s|}d}d}
nKd}d}|
|k  rB|
dz  }
 |       }	| d|	 }t        | ||      }t        |j	                               s|}n|
|k  rBt
        t        t        t               ||t        |d         t        |d         t        |d	         d
|	|||
dd}|d|d<   t        |d<   d| dg|d<   |S ||d<   t        |d<   |S )u[  collision-safe branch name 할당 (read-only, loop-until-clean).

    1. candidate = ``base_name`` → 3-source(worktree/local/remote) 전부
       absent 면 ``chosen_strategy=base`` 로 즉시 확정.
    2. 하나라도 present → ``<base_name>-<runid>`` 재생성·재검사 반복.
    3. ``max_attempts`` 회 내 clean candidate 미발견 → ``STATUS_HOLD``
       ("clean unique branch allocation 실패", 회장 §9 / 9-R.3).

    강제 reset/삭제/생성 **0** — 충돌은 새 name 회피로만 해소(회장 §3).
    반환 = branch_allocation_provenance.schema.json 와 1:1 dict.
    Nr   baser5   suffixed-r   rk   r_   rj   T)schemaallocator_moduleallocator_versionts_utcbase_shacollision_detectedsources_checkedrunidrY   chosen_strategyattempts	read_only allocated_branch_namestatusu8   clean unique branch allocation 실패 (loop-until-clean uB   회 초과, 회장 §9 / 9-R.3). 강제 reset 0 — 회장 보고.hold_reasons)rU   rY   rn   anyvaluesr   r	   r
   r$   ra   r   r   )rN   	base_namery   ro   rp   rm   live_branch
base_proberz   r|   r~   	allocatedstrategyrl   probebase_records                   r   allocate_branchr      sr   & ,I6K&y1K	9k:JZ..01 EH		%MH!OE$+Qug.I9i=Eu||~&%	 % $,.*0Z
34*W-.:h/0

  +#!K& /1+, +H!!- /00'
N#
 +4K'(,Kr   )r	   r
   r   r   r   r   r   rU   rY   r]   rb   r   )returnr<   )r   dict[str, str])rC   
str | PathrD   r<   r3   intr   ztuple[int, str])rN   r   r   r   )rN   r   r   z
str | None)rN   r   r[   r<   r   ra   )rN   r   r[   r<   r_   r<   r   ra   )rN   r   rl   r<   rm   r   r   zdict[str, bool])rN   r   r   r<   ry   r<   ro   r   rp   zCallable[[], str]r   dict)"r   
__future__r   r+   r>   re   r   r   pathlibr   typingr   r   r	   __annotations__r
   r   r   r   r   r   	Exceptionr   r$   r1   rG   rU   rY   r]   rb   rh   rn   r   __all__r   r   r   <module>r      sQ  , # 	   '  "< * < ' : ' H : H* * **Z *#$ j $/ + I9 IE <> 04( 8@		!$	14			!


  
 	
$ -'1LLL 	L
 L %L 
L^r   