
     jp=                       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m	Z	 ddl
mZ ddlmZmZ edej                  f   Z ed      Z eh d	      Z e	d
       G d d             Zd1dZd2dZdd	 	 	 	 	 d3dZddd	 	 	 	 	 	 	 d4dZd5dZdd
dd	 	 	 	 	 	 	 	 	 d6dZd7dZdd	 	 	 	 	 d8dZdd	 	 	 	 	 	 	 d9dZdd	 	 	 	 	 	 	 d:dZdd
dd	 	 	 	 	 	 	 	 	 	 	 d;dZd<dZ e!dk(  r e        Z"e"jG                         Z$e$jJ                   Z&	  ee$jN                  e&      Z(e$j\                  r		  ee(       e$j`                  r		  ee(       e$jb                  r|e$jb                  je                  d%      D  cg c]#  } | jg                         s| jg                         % c} Z4 ee(e4      Z5e5r) e+d&e4 ejX                  !        ejZ                  d'       e$jl                  r e+ ee(             y e+d(e(jN                           e+d)e(jn                           e+d*e(jp                           e+d+e(jr                           e+d,e(jt                           e+d-e(jv                           e+d.e(jx                           e+d/e(jz                           e+d0e(j|                          yy# e)$ r4Z* e+d e* ejX                  !        ejZ                  d"       Y dZ*[*dZ*[*ww xY w# e/$ r4Z* e+d e* ejX                  !        ejZ                  d#       Y dZ*[*dZ*[*ww xY w# e/$ r4Z* e+d e* ejX                  !        ejZ                  d$       Y dZ*[*dZ*[*ww xY wc c} w )=uN   canonical_workspace_resolver — deterministic workspace snapshot for 6 hooks.    )annotationsN)	dataclass)Path)CallableOptional.z/home/jay/workspace>   finish-taskscope-guardqcguardsmokemerge_executionT)frozenc                  l    e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded	<   ded
<   ded<   ded<   y)CanonicalWorkspacezEImmutable snapshot of the resolved workspace state for a single task.strtask_idr   workspace_rootworktree_pathbranch_namemain_head_shabase_shacwdboolis_mainis_cleanN)__name__
__module____qualname____doc____annotations__     9/home/jay/workspace/utils/canonical_workspace_resolver.pyr   r      s6    OLM	IMNr"   r   c                .   t        j                  | j                  t        | j                        t        | j
                        | j                  | j                  | j                  t        | j                        | j                  | j                  d	d      S )u;   Serialize CanonicalWorkspace to JSON string (Path → str).	r   r   r   r   r   r   r   r   r      )indent)jsondumpsr   r   r   r   r   r   r   r   r   r   wss    r#   to_jsonr,   /   sp    ::zz!""3"34 !1!12>>--rvv;zz
	
  r"   c                    t        | d   t        | d         t        | d         | d   | d   | d   t        | d         t        | d         t        | d	         
	      S )u7   Deserialize dict → CanonicalWorkspace (str → Path).r   r   r   r   r   r   r   r   r   r%   )r   r   r   )ds    r#   	from_dictr/   A   sk    )A./01_-.m$(:5NQy\"a
m$
 
r"   r   c               6    t        j                  | |ddd      S )z*Default subprocess runner with timeout=30.T   )r   capture_outputtexttimeout)
subprocessrun)argsr   s     r#   _default_runnerr9   T   s$     >> r"   r   runnerc               N    ||nt         } || |t        |            S d      S )z"Invoke runner with normalised cwd.Nr0   )r9   r   )r8   r   r;   fns       r#   _runr>   c   s-     %?BdCOC>>>>r"   c                   g }i }| j                         D ]  }|j                         }|j                  d      r$|r|j                  |       d|t	        d      d i}H|j                  d      r|t	        d      d |d<   k|j                  d      r|t	        d      d |d<   |dk(  sd	|d<    |r|j                  |       |S )
z@Parse `git worktree list --porcelain` output into list of dicts.z	worktree pathNzHEAD headzbranch branchbareT)
splitlinesstrip
startswithappendlen)outputentriescurrentlines       r#   _parse_worktree_listrM   n   s    GG!!# #zz|??;'w'tC$4$567G__W%"3w<=1GFO__Y' $S^_ 5GHV^"GFO# wNr"   r   fetchr;   c               x   |t        |      j                         n!t        j                         j                         }t        g d||      }d}|j                  dk(  rK|j
                  j                         r1t        |j
                  j                               j                         }||n|}t        g d||      }d}	d}
d}|j                  dk(  rt        |j
                        }|r,t        |d   j                  dd            j                         }|D ]p  }t        |j                  dd            j                         }| t        |      v s:|}	|j                  dd      }|j                  d	      r|t        d	      d }
n|}
 n t        j                  j                  d
d      j                         }|rt        |      j                         nd}||}n||}n||}nt        }|	jddl}t        |dz  |  dz        }t!        |j                  |            }|rt        |d         j                         }	n|dz  |  dz  j                         }	|
s9t        g d||      }|j                  dk(  r|j
                  j                         }
|rt        g d||       t        g d||      }|j                  dk7  s|j
                  j                         s&t#        d|j$                  j                               |j
                  j                         }|}||k(  }d}t'        | ||	|
|||||	      S )z@Resolve and lock a deterministic CanonicalWorkspace for task_id.N)git	rev-parsez--show-toplevelr:   r   )rQ   worktreelist--porcelain r@   rB   zrefs/heads/WORKSPACE_ROOTz
.worktreesz-*z-dev1)rQ   rR   z--abbrev-refHEAD)rQ   rO   originmainz--quietrQ   rR   zorigin/mainzFAILED_TO_RESOLVE_ORIGIN_MAIN: Tr%   )r   resolver   r>   
returncodestdoutrE   rM   getr   rF   rH   osenviron_DEFAULT_WORKSPACEglobsortedRuntimeErrorstderrr   )r   r   rO   r;   effective_cwdrgit_toplevel	_seed_cwdwt_rr   r   git_main_rootrJ   entry
entry_path
raw_branchenv_root_strenv_rootr   _globpattern
candidatesbr_rsha_rr   r   r   r   s                               r#   resolve_canonical_workspacerw      s'    25$s)++-dhhjFXFXFZM 	/	A
 $(L||qQXX^^-AHHNN,-557 !- 8mI2D %)MK$(M!&t{{3 !;<DDFM 		Eeii34<<>J#j/) *"YYx4
((7",S-?-@"AK",K		 ::>>"2B7==?L?KtL199;QUH &		!%		!+n|3	nDEEJJw/0
 A/779M+l:y=NNWWYM 8

 ??a++++-K 9	
 +E
 1ELL$6$6$8<U\\=O=O=Q<TUVVLL&&(MH "^3G H%##
 
r"   c                    | j                   | j                  k7  rL| j                   | j                  k7  r2t        d| j                    d| j                   d| j                         yy)zIRaise RuntimeError if ws.cwd is neither worktree_path nor workspace_root.zWRONG_CWD: cwd=z, expected=z or N)r   r   r   re   r*   s    r#   assert_cwd_matches_workspacery     sc    	vv!!!bff0A0A&AbffX[1A1A0B$rGXGXFYZ
 	
 'B!r"   )r;   c                  t        g d| j                  |      }|j                  dk7  rt        d|j                        |j
                  j                         }|| j                  k7  rt        d| j                   d|       y)zLRe-verify origin/main HEAD; raise RuntimeError if SHA drifted since resolve.r[   r:   r   z,STALE_MAIN: failed to re-check origin/main: zSTALE_MAIN: locked=z
, current=N)r>   r   r]   re   rf   r^   rE   r   )r+   r;   rv   current_shas       r#   assert_main_freshr|     s     +E
 1:5<<:JK
 	
 ,,$$&Kb&&&!""2"2!3:k]K
 	
 'r"   c               Z   |syg dt        |      z   }t        || j                  |      }|j                  dk7  rt        || j                  |      }|j                  dk7  r&t        d|j                  j                               |j                  j                         }t        |      S )z\Return True (dirty) if any expected_files have uncommitted changes; False (clean) otherwise.F)rQ   statusrU   z--r:   r   zGIT_STATUS_FAILED: )
rT   r>   r   r]   r   re   rf   rE   r^   r   )r+   expected_filesr;   r8   rh   rI   s         r#   evaluate_scope_dirtyr   2  s     1D4HHDTr''7A||q2,,V<||q01A0DEFFXX^^F<r"   c                  t        g d| j                  |      }|j                  dk7  r&t        d|j                  j                               |j                  j                         }|j                  dd      }|j                  dd      }t        t        |j                  dd                  j                         }g }||k7  r|j                  d	|d
|       | j                  |k7  r!|j                  d| j                  d
|       | j                  j                         |k7  r!|j                  d| j                   d
|        |rt        ddj                  |      z         y)zSVerify HEAD SHA, branch_name, worktree_path match finish_target; raise on mismatch.)rQ   rR   rX   r:   r   zGIT_REV_PARSE_HEAD_FAILED: head_sharV   r   r   zhead_sha: current=z != expected=zbranch_name: ws=zworktree_path: ws=zFINISH_TASK_CONTEXT_MISMATCH: z; N)r>   r   r]   re   rf   rE   r^   r_   r   r   r\   rG   r   r   join)	r+   finish_targetr;   head_rcurrent_head_shaexpected_headexpected_branchexpected_wt
mismatchess	            r#   assert_finish_task_contextr   J  sn    $FFF
 A89L9L9N8QRSS}}**,!%%j"5M#''r:Os=,,_bABCKKMKJ=( !1 4M-ARS	
 
~~(r~~0o=PQ	
 
![0 !1!1 2-}M	
 ,tyy/DD
 	
 r"   c               l    |t         vrt        d| dt        t                      t        | |||      S )zKUnified entrypoint for all 6 hook types; validates hook_name then resolves.zUNKNOWN_HOOK: z
, allowed=rN   )_ALLOWED_HOOKS
ValueErrorrd   rw   )r   	hook_namer   rO   r;   s        r#   resolve_for_hooksr   v  sJ     &YKz&2H1IJ
 	
 '	 r"   c                 $   t        j                  d      } | j                  ddd       | j                  ddd	d
       | j                  ddd       | j                  ddd       | j                  ddd       | j                  ddd       | S )Nz2Resolve and inspect CanonicalWorkspace for a task.)descriptionz	--task-idTztask-NNNN[+M] identifier)requiredhelpz--json
store_trueoutput_jsonzPrint JSON output)actiondestr   z--assert-cwdzAssert cwd matches workspace)r   r   z--assert-freshzAssert origin/main is not stalez--scopezFILE1,FILE2,...z&Evaluate scope dirty (comma-separated))metavarr   z
--no-fetchzSkip git fetch (test mode))argparseArgumentParseradd_argument)ps    r#   _build_parserr     s    H	A NN;4NNONN8L}K^N_NN>,=[N\NN#L?`NaNN9&7>fNgNN<;WNXHr"   __main__)rO   zERROR: )file   r&      ,zSCOPE_DIRTY:    ztask_id      : zworkspace_root: zworktree_path : zbranch_name  : zmain_head_sha: zbase_sha     : zcwd          : zis_main      : zis_clean     : )r+   r   returnr   )r.   dictr   r   )r8   	list[str]r   zOptional[str]r   subprocess.CompletedProcess)r8   r   r   zOptional[str | Path]r;   Optional[RunnerType]r   r   )rI   r   r   z
list[dict])
r   r   r   Optional[Path]rO   r   r;   r   r   r   )r+   r   r   None)r+   r   r;   r   r   r   )r+   r   r   r   r;   r   r   r   )r+   r   r   r   r;   r   r   r   )r   r   r   r   r   r   rO   r   r;   r   r   r   )r   zargparse.ArgumentParser)?r   
__future__r   r   r(   r`   r6   sysdataclassesr   pathlibr   typingr   r   CompletedProcess
RunnerTyperb   	frozensetr   r   r,   r/   r9   r>   rM   rw   ry   r|   r   r   r   r   r   parser
parse_argsr8   no_fetch
fetch_flagr   r+   	Exceptionexcprintrf   exit
assert_cwdre   assert_freshscopesplitrE   filesdirtyr   r   r   r   r   r   r   r   r   )fs   0r#   <module>r      s>   T "   	  
 !  %
 c:6667
/0 M $  $$, 
 
 !	$ !%#'	?
? 
? !	?
 !?8 #'~~ 
~ 	~
 !~ ~J
 $(

 !
 
	
< $(	 !	
 
8 $(	%
%
%
 !	%

 
%
` #' 
	
  ! 2
 z_FD]]"J(ZH
 	(,
 	b!
 zz$(JJ$4$4S$9GqQWWYG$R/M%)

;CHHQKgbk

|,- !2!2 345 !1!1 234/01 0 0123}-.x()

|,-}-.Y   uoCJJ/  	GC5/

3CHHQKK	  	GC5/

3CHHQKK	
 HsT   J2 3K. L* 9M&M&2K+7)K&&K+.L'3)L""L'*M#/)MM#