+
    ljk              
          R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt]P                  P                  R4      t	]P                  P                  R4      t
]! ]P                  P                  RRP4      4      t]! ]P                  P                  RR4      4      t]! ]P                  P                  R^4      4      t]! ]P                  P                  RRQ4      4      t]! ]P                  P                  R	RR4      4      t]! ]P                  P                  RR4      4      t]! ]P                  P                  RR4      4      t]! ]P                  P                  RR4      4      tRStRTt^Zt^t0 RUmtRVt]! ]P                  P                  RR4      4      tRWtRXtRYt ]! ]P                  P                  RR4      4      t!RZt"]! ]P                  P                  RR[4      4      t#]R\,           t$]PJ                  ! R4      ;'       g    ^dt&R t'R t(R t)R t*R t+R t,R t-R t.R t/R t0R]R lt1R t2R  t3R! t4R" t5R# t6R$ t7R% t8R& t9R' t:R( t;R^R) lt<R* t=R_R+ lt>R`R, lt?R_R- lt@R. tAR/ tBR`R0 ltCR1 tD]P                  ! R24      tFR3 tGRaR4 ltHR5 tIR6 tJRbR7 ltKR8 tLR9 tM]P                  ! R:4      tNR;^R<^R=^<R>R
R?R@/tORA tPRB tQR`RC ltRRD tSRE tTRF tURG tVRH tWRaRI ltXRJ tYRK tZRL t[RM t\RN t]RO t^R# )czShared candidate-classification + kill-ladder logic for agent-reaper.py
and reaper-ctl. Single source of truth for the never-kill-interactive
safety stack -- do not duplicate this logic in either caller.
Nz%~/.claude/run/agent-reaper-state.jsonz~/.claude/run/agent-reaper.logREAPER_STALE_MIN_SREAPER_CPU_THRESHOLDg      I@REAPER_CPU_SAMPLESREAPER_BLOCKED_TURN_MIN_SREAPER_BLOCKED_NOEVIDENCE_MIN_Si  REAPER_BLOCKED_CPU_MAXg      $@REAPER_BLOCKED_TIMEOUT_SLACK_SiX  REAPER_BLOCKED_CORRELATE_SREAPER_TEST_ORPHAN_MIN_AGE_SREAPER_SIDECAR_MIN_AGE_SREAPER_ORPHAN_RUNTIME_MIN_AGE_S
SC_CLK_TCKc                 :   \        4       pT p\        ^@4       F  pVP                  V4        \        RV R2R4      ;_uu_ 4       pVP	                  4       P                  RR7      pRRR4       XP                  R4      pTR8X  d    T# YV^,           R P                  4       p \        T^,          4      pY8X  g   T^8:  d   TP                  T4        T# TpK  	  V#   + '       g   i     L; i  \         d      T# i ; i  \        \        3 d      T# i ; i)	@   /proc//statrbreplaceerrorsN))setrangeaddopenreaddecodeOSErrorrfindsplitint
IndexError
ValueError)		start_pidpidspid_frawrprestppids	   &        +/home/user/.claude/bin/_agent_reaper_lib.py_read_ancestor_pidsr.   W   s   5D
C2Y	se5)400AffhooYo7 1 YYs^8 K 67|!!#	tAw<D ;$!)HHTNK % & K! 10 	 K	 J' 	
 K	sA   C1!C&C1#DC.)C1.C11D DDDc                 >    \        \        P                  ! 4       4      # )zPids in this process's own ancestor chain -- protects the invoking
claude session (e.g. when this tool is run manually from within one)
from ever becoming its own candidate.)r.   osgetpid     r-   dispatcher_exempt_pidsr4   p   s     ryy{++r3   c                    a V P                  4       o\        ;QJ d#    V3R  l\         4       F  '       g   K   R# 	  R# ! V3R  l\         4       4      # )c              3   ,   <"   T F	  qS9   x  K  	  R # 5iNr2   .0toklows   & r-   	<genexpr>!is_agent_class.<locals>.<genexpr>y   s     8%7ccz%7   TF)loweranyAGENT_CLASS_TOKENScmdliner;   s   &@r-   is_agent_classrD   w   s9    
--/C38%783383838%7888r3   c                    V \         9   d   R# VP                  4       p\        V4      ;'       d.    \        P                  P                  V^ ,          4      \         9   # )zTrue only when the process IS an agent CLI. is_agent_class() matches any
cmdline carrying an agent path token, which every wrapper and helper under
~/.claude also satisfies -- too coarse to decide tree ownership.T)rA   r    boolr0   pathbasename)commrC   partss   && r-   is_agent_sessionrK   |   sF     !!MMOE;KK277++E!H59KKKr3   c                    aa V P                  4       oVP                  4       o\        ;QJ d$    VV3R  l\         4       F  '       g   K   R# 	  R# ! VV3R  l\         4       4      # )c              3   F   <"   T F  qS9   ;'       g    VS9   x  K  	  R # 5ir7   r2   )r9   r:   low_cmdlow_comms   & r-   r<    is_denylisted.<locals>.<genexpr>   s"     LOSh00#.0Os   !!TF)r?   r@   DENYLIST_TOKENS)rI   rC   rN   rO   s   &&@@r-   is_denylistedrR      sB    zz|HmmoG3LOL33L3L3LOLLLr3   c                       \        R 4      ;_uu_ 4       p \        V P                  4       P                  4       ^ ,          4      uuRRR4       #   + '       g   i     R# ; i  \        \
        \        3 d     R# i ; i)z/proc/uptimeN)r   floatr   r    r   r#   r"   r(   s    r-   read_uptime_srV      sU    .!!Q)!,- "!!!Z, s.   A" .A
A" A	A" A" "A<;A<c                 \     \         P                  ! R V  R24      #   \         d     R# i ; i)r   z/cwdNr0   readlinkr   r&   s   &r-   read_proc_cwdr[      s1    {{VC5-..     ++c                r    V ^8:  d   R# \        V 4      pVf   R# VR,          R8X  d   R\        V 4      9   # R# )zTrue when a process's parent is init or the user systemd manager --
i.e. its real spawner died and it was reparented. A live test's runtime
still has its runner as parent, so this cleanly separates leak from live.TrI   systemd--userF)read_proc_statread_proc_cmdline)r,   psts   & r-   is_reparentedrc      s@     qy

C
{
6{i,T222r3   c                    a  \         ;QJ d#    V 3R  l\         4       F  '       g   K   R# 	  R# ! V 3R  l\         4       4      # )c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir7   r2   )r9   r:   rC   s   & r-   r<   is_sidecar.<locals>.<genexpr>   s     8#g~r>   TF)r@   SIDECAR_TOKENS)rC   s   fr-   
is_sidecarrh      s,    3883383838888r3   c                    a V P                  4       o\        ;QJ d#    V3R  l\         4       F  '       g   K   R# 	  R# ! V3R  l\         4       4      # )c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir7   r2   r8   s   & r-   r<   $is_orphan_runtime.<locals>.<genexpr>   s     ;%:ccz%:r>   TF)r?   r@   ORPHAN_RUNTIME_TOKENSrB   s   &@r-   is_orphan_runtimerm      s9    
--/C3;%:;33;3;3;%:;;;r3   c                   T p\        4       p\        V4       F  pW#9   d    R# VP                  V4       \        V4      pVf    R# VR,          pV^8:  d   Vu # \        V4      pVf   Vu # \	        V4      pVR,          R8X  d   RV9   d   Vu # VR,          ^ 8w  g   \        VR,          V4      '       d    R# TpK  	  R# )zTopmost ancestor whose chain reaches init/user-systemd without passing a
live owner. None when an owner is found: an ancestor that is agent-class or
holds a controlling terminal.Nr,   rI   r^   r_   tty_nr)r   r   r   r`   ra   rK   )	r&   	max_depthcurseenr'   str,   rb   pcmds	   &&       r-   orphan_tree_rootru      s     C5D9;C :&z19JT";J &v;)#D(8Jx=A!1#f+t!D!D% & r3   c                   aa V P                  4       o\         F  pVS9   g   K  Vu # 	  \        ;QJ d#    V3R  l\         4       F  '       g   K   RM	  RM! V3R  l\         4       4      '       ds   SR,           T;'       g    RP                  4       ,           o\        ;QJ d#    V3R l\         4       F  '       g   K   RM	  RM! V3R l\         4       4      '       d   R# R# )c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir7   r2   r8   s   & r-   r<   %test_orphan_reason.<locals>.<genexpr>   s     
<!;##:!;r>   TF  c              3   ,   <"   T F	  qS9   x  K  	  R # 5ir7   r2   )r9   markerhays   & r-   r<   rx      s     D+C}+Cr>   zruntime-under-test-pathN)r?   TEST_ORPHAN_HARNESS_TOKENSr@   TEST_ORPHAN_RUNTIME_TOKENSTEST_ORPHAN_PATH_MARKERS)rC   cwdr:   r}   r;   s   && @@r-   test_orphan_reasonr      s    
--/C)#:J * s
<!;
<sss
<!;
<<<Ci399"++--3D+CD333D+CDDD,r3   c                 j    \        R V  R2R4      ;_uu_ 4       pVP                  4       P                  RR7      pRRR4       XP	                  R4      pTP                  R4      pTR8X  g   TR8X  d   R# Y$^,           T pY#^,           R P                  4       p RTR	\        T^,          4      R
\        T^,          4      R\        T^,          4      R\        T^,          4      R\        T^,          4      /#   + '       g   i     L; i  \         d     R# i ; i  \        \        3 d     R# i ; i)r   r   r   r   r   Nr   (rI   r,   ro   utimestime	starttimer   )
r   r   r   r   r   findr    r!   r"   r#   )r&   r(   r)   r*   lprI   r+   s   &      r-   r`   r`      s   F3%u%t,,&&(///3C - 
3B	#B	Rx28Avb>DAvw<D
DCQLc$q'lSb]Sb]T"X
 	
 -, " 
# s@   D !C8D AD 8D	D D DDD21D2c                     \        R V  R2R4      ;_uu_ 4       pVP                  4       pRRR4       XP                  RR4      P	                  RR7      P                  4       #   + '       g   i     L@; i  \         d     R# i ; i)	r   z/cmdliner   Nrz           r   r   )r   r   r   r   r   strip)r&   r(   r)   s   &  r-   ra   ra      ss    F3%x($//1&&(C 0 ;;w%,,I,>DDFF	 0/ s-   A6 A#A6 #A3	.A6 3A6 6BBc                 (    \        R V  R24      ;_uu_ 4       p/ pV F7  pVP                  R4      w  rEpVP                  4       W$P                  4       &   K9  	  RRR4        \	        XP                  R^ 4      4      \	        TP                  R^ 4      4      ,           \	        TP                  R^ 4      4      ,           \	        TP                  R^ 4      4      ,           #   + '       g   i     L; i  \         d     R# i ; i  \         d     R# i ; i)r   z/io:Nrcharwchar
read_byteswrite_bytes)r   	partitionr   r   r!   getr#   )r&   r(   fieldslinekr'   vs   &      r-   read_proc_io_bytesr      s    F3%s#$$F..-a$%GGIwwy!  %FJJw*+c&**Wa2H.IIFJJ|Q/0136vzz-QR7S3TU 	V %$
  
  sB   C0 A CC0 "A:D C-	(C0 -C0 0C?>C?DDc                 P   R V  R2p\         P                  P                  R4      \         P                  ,           p \         P                  ! V4      pRpT F  p \         P                  ! \         P                  P                  Y4      4      pTP                  R4      '       d   TP                  T4      '       g   Kg   \         P                  ! T4      P                  pTe	   Yt8  g   K  TpK  	  T#   \
         d     R# i ; i  \
         d     K  i ; i  \
         d     K  i ; i)r   z/fdz~/.claude/projectsNz.jsonl)r0   rG   
expanduserseplistdirr   rY   joinendswith
startswithstatst_mtime)r&   fd_dirprojects_direntriesnewestentrytargetmtimes   &       r-   find_transcript_mtimer     s    cU#F77%%&:;bffDL**V$ F	[[f!<=F x((0A0A,0O0O	GGFO,,E >U^F  M!    		  		s5   C2 3D> D2D DDDD%$D%c                    \        V 4      pVf   R # \        V 4      p\        V 4      p\        V 4      pRV RVR,          RVRVR,          RVR,          RVR,          RVR,          RVR,          R	VR
VR\        P                  ! 4       /# )Nr&   rI   rC   r,   ro   r   r   r   io_bytestranscript_mtimenow)r`   ra   r   r   time)r&   rs   rC   r   r   s   &    r-   take_live_snapshotr   $  s    		B	z$G!#&H,S1s6
76
"X,R_GGH,tyy{ r3   c                      . p \         P                   ! R 4       F=  p\        P                  P                  V4      p V P	                  \        V4      4       K?  	  V #   \         d     KQ  i ; i)/proc/[0-9]*)globr0   rG   rH   appendr!   r#   )r%   dr&   s      r-   list_candidate_pidsr   :  s^    DYY~&ggq!	KKC! ' K  		s   AA+*A+c                       \        \        4      ;_uu_ 4       p \        P                  ! V 4      uuR R R 4       #   + '       g   i     R # ; i  \        \        P
                  3 d    / u # i ; ir7   )r   
STATE_PATHjsonloadr   JSONDecodeErrorrU   s    r-   
load_stater   E  sL    *99Q< T))* 	s+   A :
A A	A A A.-A.c                 T   \         P                  ! \         P                  P                  \        4      R R7       \        R,           p\        VR4      ;_uu_ 4       p\        P                  ! W4       RRR4       \         P                  ! V\        4       R#   + '       g   i     L-; i)Texist_okz.tmpwN)	r0   makedirsrG   dirnamer   r   r   dumpr   )statetmpr(   s   &  r-   
save_stater   M  s[    KK
+d;
v
C	c31		% 
JJsJ 
s   BB'	c                   V P                  R/ 4      p\        VR,          4      pVP                  V4      pVe   VP                  R4      VR,          8w  d   RVR,          R. R. RR/pVP                  R4      pVe   VR	,          e   VR
,          VR,          ,
          pVR	,          VR,          ,           VR,          ,
          pV^ 8  dH   V^ 8  dA   V\        ,          V,          R,          pVP                  R. 4      V.,           \        ) R VR&   RVR	,          VR,          ,           RVR
,          /VR&   VR,          e8   VP                  R. 4      RVR
,          RVR,          /.,           \        ) R VR&   VR
,          VR&   WBV&   V# )z{Mutates state['pids'] in place with a new sample for snapshot['pid'].
Resets history if starttime shows the pid was reused.r%   r&   Nr   pcpu_history
io_historylast_notified	_last_cpur   r   tsr   ticks      Y@r   	last_seen)
setdefaultstrr   HZHISTORY_MAX)	r   snapshotr%   pid_keyr   prev_cpudtdtickspcpus	   &&       r-   update_historyr   U  s    FB'D(5/"GHHWE}		+.(;2GGh{3^RWY!4) yy%H 1 =e_x~-7#hw&778G;LL6fkRK2%-D%*YY~r%BdV%Kk\]$[E.!!8G#4x7H#H$PXY^P_`E+
'$yyr:8E?J0DE>
  
<=l "%E+MLr3   c                    V P                  R / 4      p\        P                  ! 4       p\        VP                  4       4       F<  pW5,          p\	        V4      V9   d    WFP                  R^ 4      ,
          V8  d   K:  W5 K>  	  R# )r%   r   N)r   r   listkeysr!   r   )r   
alive_pids	max_age_sr%   r   r   r   s   &&&    r-   prune_historyr   r  sd    FB'D
))+C		$w<:%#		+q0I*II*UM	 %r3   c                     V '       g   R # W,
          pR pV  F  pVR,          V8:  d   TpK   M	  Vf!   V ^ ,          R,          V8  d   R # V ^ ,          pV R,          R,          pWdR,          8  # )Nr   r   r   r2   )r   r   stale_min_swindow_startbaselinepointcurrents   &&&    r-   _io_advancingr   |  st    $LH;,&H	 
 a=-a=nZ(Gj)))r3   c                    a T;'       g    \        4       pVf   \        MTpSf   \        MSo/ RV R,          bRV R,          bRV R,          bRV R,          bRV R,          bRRbR\        V R,          4      bR	\	        V R,          V R,          4      bR
V R,          V9   bRV R,          bRR bRR bRR bRRbRR bRRbpVR	,          '       g   VR
,          '       g   VR,          '       g   V# V R,          pV R,          e   W`R,          ,
          VR&   VR,          R J;'       d    VR,          V8  pV'       d   VP                  R. 4      M. p\        WV4      p	WR&   V	RJ p
V R,          f   \        V
4      VR&   M\        T;'       d    T
4      VR&   V'       d   VP                  R. 4      M. pV'       d   VR,          VR&   V\        ) R  p\        V4      \        8  ;'       d;    \        ;QJ d    V3R lV 4       F  '       d   K   RM	  RM! V3R lV 4       4      VR&   VR,          '       g   RVR&   V# VR,          '       g   RVR&   V# V R,          ^8H  pV R,          ^ 8H  pV'       d   V'       d   RMRVR&   V# )Nr&   rI   rC   r,   ro   kindzrunaway-agentagent_class
denylistedexemptr   transcript_age_sio_advancingpcpu_nowcpu_sustained_highFprogress_staleverdictNOT_CANDIDATEr   r   r   c              3   ,   <"   T F	  qS8  x  K  	  R # 5ir7   r2   )r9   r   cpu_thresholds   & r-   r<   evaluate.<locals>.<genexpr>  s     (LVm);Vr>   TWORKINGSTALE_LOW_CPUENFORCE_ELIGIBLEWARNr   )r   STALE_MIN_SCPU_THRESHOLDrD   rR   r   r   rF   CPU_SAMPLES_REQUIREDlenall)r   historyexempt_pidsr   r   resultr   transcript_frozenr   r   	io_frozenr   recent	is_orphanno_ttys   &&&&f          r-   evaluater	    s   &&K!,!4++K%2%:MMx &(8:CXiEX "*HX,>@F 	~hy&9: 	mHV$4hy6IJ	
 	(5/[0 	H%78 	D 	 	D 	e 	$ 	?F lvh//vm7L7L
5/C"#/%(4F+G%G!" 234? D D !34C  3:\2.rJ +>L)>&I"#+#'	? #'(9(G(Gi#H 6=7;;~r22L)"-z//01F$'K3G$G %M %M%(S(LV(LSSS(LV(L%L   "##%y&''+y A%Ih1$F/8V*&F9Mr3   c                   T;'       g    \        4       pRV R,          RV R,          RV R,          RV R,          RV R,          RRRR	R
R	RR/	p\        V R,          V R,          4      '       d   V# V R,          V9   d   V# \        V R,          4      '       d   V# V R,          ^ 8w  d   V# Vf   \        V R,          4      p\	        V R,          V4      pVf   V# WeR&   Vf   \        V R,          4      pV'       g   V# Vf   \        4       pVe   W R,          \        ,          ,
          VR
&   VR
,          e   VR
,          \        8  d   V# RVR&   V# )zClassify a NON-agent process as a leaked test-run orphan. Notify-only:
verdict is TEST_ORPHAN or NOT_CANDIDATE, never enforce-eligible -- these
are reaped by the interactive notification action, never autonomously.r&   rI   rC   r,   ro   r   zleaked-test-orphanreasonNage_sr   r   r   TEST_ORPHAN)	r   rR   rD   r[   r   rc   rV   r   TEST_ORPHAN_MIN_AGE_S)r   r  uptime_s
reparentedr   r  r  s   &&&&&  r-   evaluate_test_orphanr    sV   
 &&Kx(8)XiEX (HX,>H\$y/F
 Xf%x	':;;+%hy)**Q
{HUO, 3S9F~8"8F#34
 ?"k%:R%??wg&/4I"I%F9Mr3   c                   T;'       g    \        4       pRV R,          RV R,          RV R,          RV R,          RV R,          RRRR	R
R/p\        V R,          V R,          4      '       d   V# V R,          V9   d   V# \        V R,          4      '       g   V# Vf   \        V R,          4      pV'       g   V# Vf   \	        4       pVe   W R,          \
        ,          ,
          VR&   VR,          e   VR,          \        8  d   V# RVR
&   V# )zClassify a per-session helper daemon whose agent session is gone.
Auto-reaped: a sidecar without its session has no function, so there is
no decision for the user to make.r&   rI   rC   r,   ro   r   zorphaned-sidecarr  Nr   r   r   ORPHANED_SIDECAR)r   rR   rh   rc   rV   r   SIDECAR_MIN_AGE_S)r   r  r  r  r  s   &&&& r-   evaluate_orphaned_sidecarr    s
   
 &&Kx(8)XiEX (HX,>HZy/F
 Xf%x	':;;+%hy)**"8F#34
 ?"k%:R%??wg&/4E"E*F9Mr3   c                   \        V 4      pVf   R# VP                  R/ 4      P                  \        V 4      4      pVe   VP                  R4      VR,          8w  d   R# \        V\	        4       R7      pVR,          R8w  d   R# W$R&   V# )zRe-check the orphaned-sidecar criteria against the live process,
refusing on pid reuse (starttime mismatch) or a criteria change.Nr%   r   r  r   r  r   )r   r   r   r  r4   r&   r   r   r  r  s   &&   r-   verify_sidecar_before_killr         "#&Hii#''C1G'++k2h{6KK&x=S=UVFi..!:Mr3   c                   \        V 4       Fw  p\        V4      pVe   VR,          ^ 8w  d   K"  \        V4      p\        VR,          V4      '       g   \	        VR,          V4      '       d   Ka  \        V4      '       g   Kt  W3u # 	  R# )z(pid, cmdline) of the first process in root's tree running an allowlisted
dev runtime with no controlling terminal, or None if the tree holds none.Nro   rI   )collect_descendantsr`   ra   rK   rR   rm   )root_pidprs   cmds   &   r-   orphan_runtime_triggerr   '  su     !*A:H*"BvJ,,bj#0N0NS!!8O + r3   c                p   T;'       g    \        4       pV R,          pRVRV R,          RV R,          RV R,          RV R,          RRRR	R
R	RR	RR/
p\        V R,          V R,          4      '       d   V# WQ9   d   V# \        V R,          V R,          4      '       d   V# V R,          ^ 8w  d   V# Vf   \        V4      pW58w  d   V# Vf   \	        4       pVe   W R,          \
        ,          ,
          VR&   VR,          e   VR,          \        8  d   V# Vf   \        V4      pVf   V# Vw  VR
&   VR&   RVR&   V# )zClassify a process tree whose root lost its owner and which still runs a
dev runtime. Auto-reaped at the ROOT: the tree serves nobody, and reaping the
root tears down the descendants that a per-process check cannot reach.r&   rI   rC   r,   ro   r   zorphaned-runtimer  Ntrigger_pidtrigger_cmdliner   r   r   ORPHANED_RUNTIME)r   rR   rK   ru   rV   r   ORPHAN_RUNTIME_MIN_AGE_Sr   )root_snapshotr  r  root_oftriggerr&   r  s   &&&&&  r-   evaluate_orphaned_runtimer)  6  sV   
 &&K

CsFM&19mI>Vf%xx1H"GT=$4O	F ]6*M),DEE
f-}Y/GHHX!#"3'~ ?";%?"%DDwg&/4L"L(-7>4F=6"34*F9Mr3   c                   \        V 4      pVf   R# VP                  R/ 4      P                  \        V 4      4      pVe   VP                  R4      VR,          8w  d   R# \        V\	        4       R7      pVR,          R8w  d   R# W$R&   V# )zRe-check the orphaned-runtime criteria against the live tree, refusing on
pid reuse (starttime mismatch) or a criteria change since the scan.Nr%   r   r  r   r$  r   )r   r   r   r)  r4   r  s   &&   r-   #verify_orphaned_runtime_before_killr+  a  r  r3   zF/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/tasks/c                 \     \         P                  ! R V  R24      #   \         d     R# i ; i)r   z/fd/1NrX   )	child_pids   &r-   child_stdout_pathr.  t  s1    {{VI;e455 r\   c                "   V '       d   V P                  R4      '       g   R#  \        P                  P                  V 4      #   \         d     Mi ; iTf   R#  \        P                  P                  RT RT  24      #   \         d     R# i ; i)zySize of the tool's output file; falls back through the child's mount
namespace (/proc/<pid>/root) for tmpjail'd sessions./Nr   z/root)r   r0   rG   getsizer   )rG   r-  s   &&r-   output_file_sizer2  {  s     ts++wwt$$ ww	{%v>?? s#   A AA$A? ?BBc                t   \        V 4      pVf   R# \        P                  V4      pV'       g   R# . p\         Fd  pVP	                  \
        P
                  ! \        P                  P                  VP                  VP                  ^4      R7      4      4      4       Kf  	  V'       g   R# R p\        W5R7      # )a@  A tool child's stdout targets .../<session-uuid>/tasks/<id>.output;
that uuid names the session transcript. Sessions run under per-account
CLAUDE_HOMEs too, and a crash-journal hook seeds tiny synthetic stubs at
the same name -- search every home and prefer the largest file so a real
transcript always wins over a stub.N)uc                 h     \         P                  P                  V 4      #   \         d    Ru # i ; i)   r   )r0   rG   r1  r   r  s   &r-   _size(transcript_path_for_child.<locals>._size  s.    	77??1%% 	I	s   ! 11key)r.  _SESSION_UUID_REsearchTRANSCRIPT_GLOBSextendr   r0   rG   r   formatgroupmax)r-  r   mhitspatr8  s   &     r-   transcript_path_for_childrF    s     y)F~'ADDIIbgg00aggaj1IJKL  
 tr3   c                     V '       g   R #  ^ RI H p VP                  V P                  RR4      4      P                  4       #   \         d     R # i ; i)N)datetimeZz+00:00)rH  fromisoformatr   	timestampr#   )r   rH  s   & r-   _parse_event_tsrL    sG    %%%bjjh&?@JJLL s   4A AAc           	        V '       g   R#  \        V R4      ;_uu_ 4       pVP                  ^ ^4       VP                  4       pVP                  \        ^ W1,
          4      4       VP	                  4       P                  RR7      P                  R4      pRRR4       \        X4       EF  pTP                  4       pT'       g   K   \        P                  ! T4      pTP                  R4      pTR8X  d   TP                  R4      ;'       g    / P                  R	4      p\        T\        4      '       d   TM. p	\         ;QJ d    R
 T	 4       F  '       g   K   RM	  RM! R
 T	 4       4      p
T
'       d   R\#        TP                  R4      4      3u # Ru # TR8X  g   K  TP                  R4      ;'       g    / P                  R	4      p\        T\        4      ;'       d5    \         ;QJ d    R T 4       F  '       g   K   RM	  RM! R T 4       4      pT'       g   TP                  R4      '       d   EK  Ru # 	  R#   + '       g   i     EL; i  \         d    Ru # i ; i  \         d     EK  i ; i)a  (status, blocked_since_epoch) from the transcript tail.
'in-flight'   -- newest assistant event still ends in a tool_use: the turn
                 is waiting on a tool result and cannot advance;
                 blocked_since is that event's timestamp (immune to mtime
                 noise from queued messages/attachments).
'advancing'   -- a newer tool_result or real user message exists.
'no-evidence' -- transcript missing, or only stub/marker lines (a wedged
                 session that never produced a real event).Nr   r   r   
type	assistantmessagecontentc              3   z   "   T F1  p\        V\        4      ;'       d    VP                  R 4      R8H  x  K3  	  R# 5i)rO  tool_useN
isinstancedictr   r9   bs   & r-   r<   #read_turn_status.<locals>.<genexpr>  s2     `Y_TUJq$/OOAEE&MZ4OOY_   ;;TF	in-flightrK  userc              3   z   "   T F1  p\        V\        4      ;'       d    VP                  R 4      R8H  x  K3  	  R# 5i)rO  tool_resultNrU  rX  s   & r-   r<   rZ    s2     "kcj^_:a#6#Y#Y155=M;Y#Ycjr[  isMeta)no-evidenceN)	advancingN)r   seektellrB  r   r   r    r   reversedr   r   loadsr#   r   rV  r   r@   rL  )transcript_path
tail_bytesr(   sizelinesr   objtrR  blocks	in_flighthas_tool_results   &&          r-   read_turn_statusrp    s    ""#/4((AFF1aL668DFF3q$+,-FFHOO9O5;;DAE	 ) zz|	**T"C GGFOwwy)//R44Y?G *7D 9 9WrF`Y_``Y_``ILU[/#''+2F"GH .,.;wwy)//R44Y?G)'48  l  l"s"kcj"ksss"kcj"kk cggh&7&7(()  * 9 )((
  #""#  		sA   I A3H>I I%>I		I I I"!I"%I54I5c                    . pVP                  V . 4       F8  p\        V4      pVe   VR,          \        9  d   K&  VP                  W434       K:  	  VP	                  R R7       V# )zDirect shell children of an agent process (its Bash tool calls and any
user-backgrounded tasks), oldest first, as (pid, stat) pairs.rI   c                 "    V ^,          R,          # )r6  r   r2   r7  s   &r-   <lambda>*find_tool_shell_children.<locals>.<lambda>  s    1Q4,r3   r:  )r   r`   TOOL_SHELL_COMMSr   sort)	agent_pid	child_mapoutcrs   s   &&   r-   find_tool_shell_childrenr{    s`     C]]9b)A:F+;;

A7	 *
 HH,H-Jr3   c                 $   ^ pV .p\        4       pV'       dy   VP                  4       pWT9   d   K   VP                  V4       \        V4      pVe   W&R,          VR,          ,           ,          pVP	                  VP                  V. 4      4       K  V# )    r   r   )r   popr   r`   r?  r   )r  rx  totalstackrr   rq   rs   s   &&     r-   subtree_cpu_ticksr    sv    EJE5D
iik;C >[2g;..EY]]3+,Lr3   z(\d+)([smhd]?)$rz   srC  hr   iQ c                    Rp\         P                  ! RT ;'       g    R4       F  pVP                  ^4      P                  4       p^ pV\	        V4      8  g   K6  W4,          pVR9   d   V^,          pK,  VP                  R4      '       d   V^,          pKN  \        P                  V4      pV'       dH   \        VP                  ^4      4      \        VP                  ^4      ,          ,          pVe   Wq8  d   TpK  	  V# )zLargest `timeout [flags] N[smhd]` bound present in a command, in seconds.
Skips flag arguments (`-k 30`, `-s TERM`) so they are never read as the bound.Nz\btimeout\s+([^|;&()]{0,120})rz   -)z-kz--kill-afterz-sz--signal)
refinditerrA  r    r   r   _DURATION_RE	fullmatchr!   _DURATION_MULT)rC   bestrC  toksirl  r   secss   &       r-   parse_timeout_bound_sr    s     D[[97==bIwwqz!#d)mA<<Q||C  Q&&q)A1771:
)CC<4;D! J" Kr3   c           
       aaaa \        W4      pV'       g   RV R&   R# V P                  R4      ;'       g    / P                  R4      pV'       g   \        V^ ,          ^ ,          4      p\        V4      w  po\	        4       oVV3R loV^ ,          w  rxSe   S'       d   \        VVV3R lR7      w  rxV P                  R4      p	V	'       d4   V	P                  R4      V8w  g   V	P                  R4      VR	,          8w  d   RVRVR	,          R
\        V4      R. RR/p	WYR&   WiR&   SV	R&   S! V4      V	R&   V	P                  R4      '       g   \        V4      V	R&   \        V	P                  R4      V4      p
V	P                  R4      e   WP                  R4      8w  d   SV	R&   WR&   \        Ws4      pV	P                  R4      pVen   SVR,          ,
          pWR,          ,
          pV^ 8  dH   V^ 8  dA   V\        ,          V,          R,          pV	P                  R. 4      V.,           \        ) R V	R&   RSRV/V	R&   WR&   V	# )a  Track the agent's in-flight tool-shell child inside its state entry,
accumulating subtree-CPU%% samples. Resets on child identity change.
When the transcript names the pending tool_use, the child whose start time
matches it is tracked -- never an older user-backgrounded task.Nturnrg  c                 \   < S'       d#   SS,
          V R ,          \         ,          ,           # R# )r   N)r   )rs   r   uptimes   &r-   
wall_start'update_turn_history.<locals>.wall_start"  s"    8>fr+33HDHr3   c                 B   < \        S! V ^,          4      S,
          4      # )r6  )abs)r  blocked_sincer  s   &r-   rs  %update_turn_history.<locals>.<lambda>(  s    c*QqT*:]*J&Kr3   r:  r-  child_startr   child_cmdliner   _lastturn_statusblocked_since_tschild_wall_startoutput_pathlast_output_progressoutput_sizer   r   r   )r{  r   rF  rp  rV   minra   r.  r2  r  r   r   )r   rw  r   rx  childrenrg  statuscpidcstr  osizer   lastr   r   r   r  r  r  s   &&f&            @@@r-   update_turn_historyr    s&   
 (	=Hfyy(..B334EFO3HQKNC,_=FM_FI ID VKM	 99VDDHH[)T1xx&#k*::T=#k2B!24!8GT3 .	 ,D	)#D	88M""/5]TXXm4d;Exx&'/5HH]<S3S'*#$d.E88GD4:g&6fkRK2%-D$(HH^R$@D6$IK<=#YD 3/DM&MKr3   c                  a T;'       g    \        4       pVf   \        MTpSf   \        MSoRV R,          RV R,          RV R,          RV R,          RV R,          RRR	RR
RRRRRRRRRRRRRRR/p\        V R,          V R,          4      '       g'   V R,          V9   g   \	        V R,          4      '       g   V# T;'       g    / P                  R4      pV'       g   V# VP                  R4      pWR&   VR!9  d   V# VR	,          VR	&   VP                  R
4      VR
&   V R,          p	Vf   \        4       pVf   V# W7R,          \        ,          ,
          VR&   VR8X  dw   VP                  R4      p
V
'       dM   W,
          VR&   VR,          V8  d   V# VP                  R4      pVe   \        W,
          4      \        8  d   V# VR,          V8  d   V# M-VP                  R4      '       g   V# VR,          \        8  d   V# VP                  R4      pVe+   W,
          VR&   VR8X  d   TM\        pVR,          V8  d   V# \        VP                  R
4      4      pWR&   Ve!   VR,          V\        ,           8  d   RVR&   V# VP                  R. 4      \        ) R pV'       d   VR",          VR&   \        V4      \        8  gA   \        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       d   V# R VR&   V# )#a  Classify an agent whose turn is stuck on a low-CPU blocked tool call.
Notify-only: verdict BLOCKED_TURN or NOT_CANDIDATE, never enforce-eligible.
The remediation target is the CHILD (kills the blocked command so the turn
resumes with a failed tool result), never the agent itself.Nr&   rI   rC   r,   ro   r   zblocked-turnr-  r  child_age_schild_pcpu_nowblocked_age_stimeout_bound_sr  output_quiet_sr   r   r  r\  r   r  r  r  rg  r  BOUNDED_WAITr   c              3   ,   <"   T F	  qS8  x  K  	  R # 5ir7   r2   )r9   r   cpu_maxs   & r-   r<   (evaluate_blocked_turn.<locals>.<genexpr>  s     0Nv!gvr>   TFBLOCKED_TURN)r\  ra  r   )r   BLOCKED_TURN_MIN_SBLOCKED_CPU_MAXrR   rD   r   rV   r   r  BLOCKED_CORRELATE_SBLOCKED_NOEVIDENCE_MIN_Sr  BLOCKED_TIMEOUT_SLACK_Sr   r   r@   )r   r  r  r  blocked_min_sr  r  r  r  r   r  r  	last_prog	quiet_barboundr  s   &&&&&f          r-   evaluate_blocked_turnr  G  s    &&K*7*?&]M!(ogG 	x(8)XiEX (HX,>T?D-$7H$t-tYF 	hv&(;<<+-!(9"566MMrv&DXXm$F"=11{+F;"hh7F?
5/C ?$M':R'??F=!34&)&9F?#o&6"45J&J67:MM- =0M 1 xx)**M- #;;M
 /0I#&? %+{%:M@X	"#i/M!$((?";<E %VM2U=T5TT*yXXnb)+?*?*@AF#)": 
6{))SS0Nv0NSSS0Nv0N-N-N&F9Mr3   c                n   \        V 4      pVf   R# VP                  R/ 4      P                  \        V 4      4      pVe   VP                  R4      VR,          8w  d   R# \        W#\	        4       R7      pVR,          R8w  d   R# \        VR,          4      pVe   VR,          VR,          R	,          8w  d   R# VR,          p\        VP                  R
4      4      w  rxVR8X  d   R# VP                  R4      e9   \        VP                  R4      VP                  R4      4      VR,          8w  d   R# W$R&   V# )zIRe-check blocked-turn criteria live; refuses on agent or child pid reuse.Nr%   r   r  r   r  r-  r  r  rg  rb  r  r  r   )r   r   r   r  r4   r`   rp  r2  )	rw  r   r   r  r  r  r  r  r'   s	   &&       r-   verify_blocked_turn_before_killr    s   !),Hii#''I7G'++k2h{6KK"8BXBZ[FiN*
,
-C
{c+&'&/-*HH6?D *;!<=IF+ -!8$((;:OPTXYfTgg!:Mr3   c                  ,   / p \         P                   ! R 4       Fe  p \        \        P                  P	                  V4      4      p\        T4      pTf   K=  T P                  TR,          . 4      P                  T4       Kg  	  V #   \
         d     Ky  i ; i)r   r,   )	r   r!   r0   rG   rH   r#   r`   r   r   )r  r   r&   rs   s       r-   build_child_mapr    s    HYY~&	bgg&&q)*C C :BvJ+2237 ' O  		s   (BBBc                "   \        4       p. pV .p\        4       pV'       d^   VP                  4       pWT9   d   K   VP                  V4       VP	                  V4       VP                  VP                  V. 4      4       Ke  VP                  4        V# )zYpid plus every transitive child, leaves first, so a tree is torn down
from the bottom up.)r  r   r~  r   r   r?  r   reverse)r&   r  orderedr  rr   rq   s   &     r-   r  r    sr      HGEE5D
iik;sX\\#r*+OONr3   c                    \        V 4      pVf   R# VP                  R/ 4      P                  \        V 4      4      pVe   VP                  R4      VR,          8w  d   R# \        V\	        4       R7      pW$R&   V# )zRe-check the leaked-orphan criteria against the live process, refusing
on pid reuse (starttime mismatch) or a criteria change since the scan.Nr%   r   r  r   )r   r   r   r  r4   r  s   &&   r-   verify_test_orphan_before_killr    sp     "#&Hii#''C1G'++k2h{6KK!(8N8PQF!:Mr3   c                t   \        V 4      pV F)  p \        P                  ! V\        P                  4       K+  	  \        RRRV RVRV/4       \        P                  ! 4       \        ,           p\        P                  ! 4       V8  df   \        ;QJ d    R V 4       F  '       d   K   R	M	  R
M! R V 4       4      '       d   \        RRRV RV/4       R# \        P                  ! R4       K  V Uu. uF  p\        V4      '       d   K  VNK  	  ppV F)  p \        P                  ! V\        P                  4       K+  	  \        RRRV RV/4       \        P                  ! 4       ^,           p\        P                  ! 4       V8  df   \        ;QJ d    R V 4       F  '       d   K   R	M	  R
M! R V 4       4      '       d   \        RRRV RV/4       R# \        P                  ! R4       K  R#   \
         d     EK  \         d    \        RRRTRT RT/4        EK  i ; iu upi   \
         d     EK#  i ; i)zGSIGTERM the whole subtree, wait, SIGKILL survivors. Returns an outcome.actionreap_deniedr&   rootevidencereap_SIGTERMtreec              3   8   "   T F  p\        V4      x  K  	  R # 5ir7   pid_gone_or_zombier9   r  s   & r-   r<   reap_tree.<locals>.<genexpr>       3d!!$$d   FTreaped      ?reap_SIGKILL	survivorsc              3   8   "   T F  p\        V4      x  K  	  R # 5ir7   r  r  s   & r-   r<   r    r  r  g?partial)r  r0   killsignalSIGTERMProcessLookupErrorPermissionError	log_eventr   KILL_WAIT_Sr   sleepr  SIGKILL)r&   r  r%   r  deadliner  graces   &&     r-   	reap_treer    s   s#D	^GGAv~~&  xfdJPXYZyy{[(H
))+
 33d33333d333x63EF

3 >Dq(:1(=DI>	GGAv~~& 
 xk9MN IIK!OE
))+
33d33333d333x63EF

3; " 	 	^xq&#zS[\]]	^ ? " 		s;   %G.1H"	H"%H'.H=HHH'H76H7c                     \        V 4      pVf   R # VP                  R/ 4      P                  \        V 4      / 4      p\        W4VR7      # )Nr%   r  )r   r   r   r	  )r&   r   r  r   r  s   &&&  r-   classify_pid_liver  
  sC    !#&Hii#''C"5GH;??r3   c                    \        V 4      pVf   R# \        V 4      pVP                  R/ 4      P                  V4      pVe   VP                  R4      VR,          8w  d   R# \        4       p\	        W$VR7      pW&R&   V# )zxRe-check candidate criteria against the LIVE process right now.
Refuses (returns None) on pid reuse or resumed progress.Nr%   r   r  r   )r   r   r   r4   r	  )r&   r   r   r   r  r   r  s   &&     r-   verify_live_before_killr    sy     "#&H#hGii#''0G'++k2h{6KK#%FhV<F!:Mr3   c                   V P                  R/ 4      p\        P                  ! 4       p\        4       pV Fq  pVR,          R9   g   K  \        VR,          4      pVP	                  V4       VP                  V4      pV'       d
   VR,          MTp\        V4      p	WR&   W9R&   WV&   Ks  	  \        VP                  4       4       F  pWd9  g   K  W& K  	  V# )zKeep state['flagged'] in sync with current WARN/ENFORCE_ELIGIBLE
candidates. reaper-notifier watches this for NEW pids to notify on;
it clears when a pid stops being a candidate (resumed, exited, denylisted).flaggedr   r&   first_flagged_tslast_seen_ts)r   r   r  )	r   r   r   r   r   r   rW  r   r   )
r   resultsr  r   rr   rr   existingfirst_tsr   s
   &&        r-   refresh_flaggedr  "  s     y"-G
))+C5DY<FF!E(mGHHW{{7+H7?x 23SHGE(0$%$'.!$G  '  ( Nr3   c                 t     \         P                  ! V ^ 4       R#   \         d     R# \         d     R# i ; i)r}  FT)r0   r  r  r  rZ   s   &r-   	pid_aliver  9  s8    
Q
 	   s    7777c                l    \        RV  R2R4      ;_uu_ 4       pVP                  4       P                  RR7      pRRR4       XP	                  R4      pTR
8X  d   R# Y#^,           R P                  4       pT'       * ;'       g    T^ ,          R	8H  #   + '       g   i     L^; i  \         d     R# i ; i)zA SIGKILLed process is briefly a zombie (state Z) until its parent or a
subreaper reaps it -- os.kill(pid, 0) still succeeds then, so treat Z as
gone or a tree tear-down reports a false 'partial'.r   r   r   r   r   NTr   rI  r   )r   r   r   r   r   r    )r&   r(   r)   r*   r+   s   &    r-   r  r  C  s    F3%u%t,,&&(///3C - 
3B	RxAvw<DH''aC' -, s-   B$ !BB$ B!	B$ !B$ $B32B3c           	         \         P                  ! \         P                  P                  \        4      R R7       \        V 4      p \        P                  ! 4       V R&   \        \        R4      ;_uu_ 4       pVP                  \        P                  ! V \        R7      R,           4       RRR4       R#   + '       g   i     R# ; i)Tr   r   a)defaultrN  N)r0   r   rG   r   LOG_PATHrW  r   r   writer   dumpsr   )eventr(   s   & r-   r  r  S  so    KK)D9KE))+E$K	h			

5#.56 
			s   53B22C	c                    \         P                  ! V \        P                  4       \        RR
RT RT/4       \        P                  ! 4       \        ,           p\        P                  ! 4       T8  d=   \        T 4      '       g   \        RRRT RT/4       R# \        P                  ! R4       KV  \        T 4      '       d:    \         P                  ! T \        P                  4       \        RRRT RT/4       R# R#   \         d    \        RRRT RRRT/4        R# \         d    \        RRRT RT/4        R	# i ; i  \         d    \        RRRT RT/4        R# i ; i)z=SIGTERM, wait, re-verify+SIGKILL. Returns the outcome string.r  	kill_skipr&   r  zalready goner  already_gonekill_deniedpermission_deniedr  
terminatedr  r  killed)r0   r  r  r  r  r  r  r   r  r  r  r  )r&   r  r  s   && r-   kill_ladderr  [  s.   #
V^^$ xE3
HEFyy{[(H
))+
 ~~xuc:xPQ

3~~	 GGC(xE3
HMN /  8[%hPZ\def #8]E3
HMN"#" " 	 xuc:xPQ	 s/   %C:  6D= :D:D:$D:9D:=EEi
  i  i   )bashshzsh)z~/.claude/projects/*/{u}.jsonlz@~/.systray-ai/claude-accounts/*/CLAUDE_HOME/projects/*/{u}.jsonl>   ccrqemucinnamonharnessdpipewireagent_guard
reaper-ctlhw-blackboxqemu-systemagent-reapervirt-managerreaper-notifier)claudezcursor-agent)z"ci-integration-http-signal-harnesszci-integration-httpzci-with-disposablezci-neon-branchzci-oracle-databaserunner-integration)zsleep infinitywranglervitest
playwrightesbuild)z.wt-z/.claude/worktrees/z	agent-tmpr  z/apps/web/scripts/ci-)zquietmode/start.mjsi@8  )viteastroz
e2e-remoteworkerd)r   )i0*  )NNN)NNNNr7   )i   )___doc__r   r   r0   r  r  r   rG   r   r   r  r!   environr   r   rT   r   r   r  r  r  r  r  ru  r>  r   r  rQ   rA   r  r~   r   r   r  rg   r%  rl   sysconfr   r.   r4   rD   rK   rR   rV   r[   rc   rh   rm   ru   r   r`   ra   r   r   r   r   r   r   r   r   r   r	  r  r  r  r   r)  r+  compiler<  r.  r2  rF  rL  rp  r{  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r2   r3   r-   <module>r$     s7     	 	  WW GH
77>?"**..!5w?@bjjnn%;TBC2::>>*>BC  (CWMN rzz~~.OQYZ[ 

'?FGbjjnn-MsST "**..)EsKL (   
 0  BJJNN+I7ST   _ 5  

'A7KL ) rzz~~.OQYZ[ 2 6A A  ZZ$$2,9
LM9<
8	2G 0, :*$9x(VD (V  ::gh " 2(V
  zz,-aab#tS%@01hSl2$#L@ .( 7r3   