+
    „WÝjAV  ã                  óv  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
Ht ^ RIHt ^ RIt]P                   ! ]4      tRt^tR't^t ! R R]4      tR R	 ltR
 R ltRtRtRtR R ltR R ltR R ltR R lt R R lt!R R lt"R R lt#]3R R llt$R R  lt%R! R" lt&R(R# R$ llt'R% R& lt(R# ))aÉ  Scratch-dir retention: idle detection plus the reaping an idle tree needs before it goes.

Deleting an idle ``cache/scratch/<entry>`` is not enough on its own: a lane's e2e run leaves
headless browsers whose cwd was inside the tree (they survived for days with a ``(deleted)``
cwd), and a repo whose linked worktree lived in the tree keeps a dangling registration until
someone runs ``git worktree prune``. Both are reaped here, right before ``rmtree``.

A process Hermes itself started is never an orphan, though: an idle entry a registered live
process still works inside is kept, not reaped (#132401). Ownership comes from the two
registries Hermes writes, not from a marker file a lane must remember to drop.
)ÚannotationsN)ÚRotatingFileHandler)ÚPathg      @c                  ó2   a € ] tR t^(tRtR V 3R lltRtV ;t# )Ú_PruneLogHandlera,  Rollover that tolerates a concurrent prune of the same home rotating first: its rename
of ``scratch-prune.log`` can land between this handler's existence check and its own
rename. The rotation is then already done, so the record goes to the new file instead of
being dropped with a FileNotFoundError.c               ó   € V ^8„  d   QhRR/# )é   ÚreturnÚNone© )Úformats   "ÚLC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_constants_scratch.pyÚ__annotate__Ú_PruneLogHandler.__annotate__.   s   € ÷ !ñ !˜Dñ !ó    c                	ó¢   <€ \         P                  ! \        4      ;_uu_ 4        \        SV `  4        R R R 4       R #   + '       g   i     R # ; i©N)Ú
contextlibÚsuppressÚFileNotFoundErrorÚsuperÚ
doRollover)ÚselfÚ	__class__s   &€r   r   Ú_PruneLogHandler.doRollover.   s/   ø€ Ü× Ò Ô!2×3Õ3Ü‰GÑÔ ÷ 4×3×3Ò3ús	   ¤=½A	r   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   Ú__static_attributes__Ú__classcell__)r   s   @r   r   r   (   s   ø† ñ/÷
!ö !r   r   c               ó    € V ^8„  d   QhRRRR/# )r   Úlog_fileúPath | Noner	   úlogging.Loggerr   )r   s   "r   r   r   3   s   € ÷ ñ ˜kð ¨nñ r   c           	     óî  € V f   \         #  V P                  P                  RRR7       \
        P                  ! \         P                  \
        P                  4      p\         Tn        \        T \        \        RRRR7      pTP                  \
        P                  ! R4      4       TP                  T4       T#   \         d2   p\         P	                  RT P                  T4       \         u Rp?# Rp?ii ; i)	a  Logger for one prune's records, with its own RotatingFileHandler on *log_file*, so a
prune that runs at boot (before ``setup_logging()``) still leaves them on disk. Records also
propagate through this module's logger to whatever logging is set up.

One unregistered logger per prune, closed when it ends: no process holds the file open
between prunes (an open handle blocks rollover on Windows), and prunes of two homes never
share a handler. Without a *log_file* (test-runner temp roots) this module's logger is used.
NT)ÚparentsÚexist_okz#scratch prune: cannot create %s: %súutf-8Úbackslashreplace)ÚmaxBytesÚbackupCountÚencodingÚerrorsÚdelayz%(asctime)s %(message)s)ÚloggerÚparentÚmkdirÚOSErrorÚwarningÚloggingÚLoggerÚnameÚINFOr   Ú_PRUNE_LOG_MAX_BYTESÚ_PRUNE_LOG_BACKUPSÚsetFormatterÚ	FormatterÚ
addHandler)r#   ÚexcÚauditÚhandlers   &   r   Ú_open_prune_logrA   3   sÄ   € ð ÒÜˆðØ�‰×Ñ d°TÐÔ:ô �NŠNœ6Ÿ;™;¬¯©Ó5€EÜ€E„Lô ØÔ/Ô=OÐZaØ!¨ô€Gð ×Ñœ×*Ò*Ð+DÓEÔFØ	×Ñ�WÔØ€Løô ô Ü�‰Ð<¸h¿o¹oÈsÔSÜ�ûðús   ŒB8 Â8C4Ã&C/Ã)C4Ã/C4c               ó    € V ^8„  d   QhRRRR/# )r   Úpathr   r	   Úintr   )r   s   "r   r   r   P   s   € ÷ ñ �dð ˜sñ r   c                ó’  €  \         P                  ! V 4      P                  pT P	                  4       '       d#   T P                  4       '       g   \        T 4      .M. pT'       dš    \         P                  ! TP                  4       4      ;_uu_ 4       pT F[  p YP                  RR7      P                  ,          pTP	                  RR7      '       g   K@  TP                  TP                  4       K]  	  RRR4       K¡  T#   \         d     ^ # i ; i  \         d     K‹  i ; i  + '       g   i     KØ  ; i  \         d     Ké  i ; i)zGApparent size of *path* and everything under it, symlinks not followed.F©Úfollow_symlinksN)ÚosÚlstatÚst_sizer3   Úis_dirÚ
is_symlinkÚstrÚscandirÚpopÚstatÚappendrC   )rC   ÚtotalÚstackÚitÚchilds   &    r   Ú_tree_bytesrV   P   sþ   € ðÜ—’˜“×&Ñ&ˆð  Ÿ;™;Ÿ=š=°·±×1BÒ1BŒS�‹Y‰KÈ€Eß
ð
	Ü—’˜EŸI™I›K×(Ô(¨BÛ�Eð!Ø§¡¸E Ó!B×!JÑ!JÕJ˜ð —|‘|°E�|×:Ô:ØŸ™ U§Z¡ZÖ0ñ  ÷ )Ñ(ð €Løô ô Úðûô #ô !Ú ð!ú÷	 )×(Ð(ûô ô 	Úð	úsk   ‚ C? Á%,D7 ÂD#Â"DÂ:D#ÃD#Ã3D7 Ã?DÄDÄD 	ÄD#ÄD 	Ä D#Ä#D4	Ä.D7 Ä4D7 Ä7EÅEÚtouchedzscan-failedÚidlec               ó$   € V ^8„  d   QhRRRRRR/# )r   rC   r   ÚcutoffÚfloatr	   rM   r   )r   s   "r   r   r   k   s!   € ÷ *ñ *˜dð *¨Eð *°cñ *r   c                ó&   € \        W4      ^ ,          # )uÝ  Tri-state form of :func:`subtree_touched_since`: ``touched`` (recent write seen),
``scan-failed`` (unreadable â€” idle cannot be established, so the entry is kept, but
a failed scan is not activity and is never reported as such), or ``idle``.
Same walk, same stop-at-first-recent shortcut, same symlink rules. A hardlinked file
(``st_nlink > 1``) does not count either: its mtime is the inode's, and
``git clone --local`` hardlinks packs that git freshens from the source repo.)Ú_scan_subtree©rC   rZ   s   &&r   Úsubtree_touch_stater_   k   s   € ô ˜Ó& qÕ)Ð)r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rC   r   rZ   r[   r	   ztuple[str, str | None]r   )r   s   "r   r   r   u   s"   € ÷ ñ ˜ð  eð Ð0Fñ r   c                ó  €  \         P                  ! V 4      P                  V8¼  d	   \        R3# V P	                  4       '       d   V P                  4       '       d	   \        R3#  \        T 4      .pT'       dÚ   TP                  4       p \         P                  ! T4      ;_uu_ 4       pT F™  p TP                  RR7      pTP                  T8¼  d>   TP                  ^8”  d   TP!                  RR7      '       g   \        R3u uuRRR4       # TP	                  RR7      '       g   K~  TP#                  TP$                  4       K›  	  RRR4       Ká  \        R3#   \         d    \        R3u # i ; i  \         d=   p\        \        P                  ! T4      '       d   TMR3u Rp?u uuRRR4       # Rp?ii ; i  + '       g   i     EK^  ; i  \         d1   p\        \        P                  ! T4      '       d   TMR3u Rp?# Rp?ii ; i)z˜``(state, denied_dir)``: *denied_dir* is the directory below *path* that refused
listing with EACCES/EPERM when that is why the scan failed (else None).NFrF   )rH   rI   Úst_mtimeÚ_TOUCHEDrK   rL   Ú_IDLEr3   Ú_SCAN_FAILEDrM   rO   rN   rP   ÚstuckÚis_permission_errorÚst_nlinkÚis_filerQ   rC   )rC   rZ   rS   ÚcurrentrT   rU   Ústr>   s   &&      r   r]   r]   u   s¤  € ð"Ü�8Š8�D‹>×"Ñ" fÔ,Ü˜T�>Ð!Ø�{‰{�}Š} §¡× 1Ò 1Ü˜$�;Ðð !2ô �‹YˆK€Eß
Ø—)‘)“+ˆð	UÜ—’˜G×$Ô$¨Û�EðaØ"ŸZ™Z¸˜ZÓ>˜ð —{‘{ fÔ,°b·k±kÀA´oÈ%Ï-É-ÐhmÈ-×JnÒJnÜ'¨˜~Ñ-÷ %Ò$ð —|‘|°E�|×:Ô:ØŸ™ U§Z¡ZÖ0ñ  ÷ %Ñ$ô �$ˆ;Ðøô% ô "Ü˜TÐ!Ò!ð"ûô #ô aÜ+¼×8QÒ8QÐRU×8VÒ8V©WÐ\`Ð`Ö`÷ %Ò$ûðaú÷	 %×$Ñ$ûô ô 	UÜ¬E×,EÒ,EÀc×,JÒ,J¡ÐPTÐTÕTûð	Uús¬   ‚,E ¯E ÁE ÁE Â	G Â'F<Â.E2Ã 9F<Ã:	F<Ä
G ÄF<Ä(F<ÅG ÅE/Å.E/Å2F9	Å=%F4	Æ"F9	Æ#F<Æ)
G Æ4F9	Æ9F<Æ<G	ÇG ÇG ÇHÇ%HÈHÈHc               ó$   € V ^8„  d   QhRRRRRR/# )r   rC   r   rZ   r[   r	   Úboolr   )r   s   "r   r   r   ’   s!   € ÷ 
6ñ 
6 ð 
6¨eð 
6¸ñ 
6r   c                ó&   € \        W4      \        8g  # )u<  True when *path* or anything beneath it has an mtime at or after *cutoff*.

Stops at the first recent entry, so a live tree costs one hit and only a truly idle
tree pays for the full walk (once, right before it is deleted). Symlinks are never
followed: a link into the repo would make the target's activity keep the entry alive.
An unreadable entry is kept: an incomplete scan cannot establish that it is idle â€”
so True here means "touched **or** uninspectable", and callers that need to tell the
two apart (the mid-prune audit) use :func:`subtree_touch_state` instead.
)r_   rd   r^   s   &&r   Úsubtree_touched_sincero   ’   s   € ô ˜tÓ,´Ñ5Ð5r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rC   rM   Úrootr	   rm   r   )r   s   "r   r   r   Ÿ   s&   € ÷ Iñ I�ð I˜Cð I Dñ Ir   c                ó    € W8H  ;'       gD    V P                  VP                  \        P                  4      \        P                  ,           4      # r   )Ú
startswithÚrstriprH   Úsep)rC   rq   s   &&r   Ú_underrv   Ÿ   s1   € Ø‰<×HÐH˜4Ÿ?™?¨4¯;©;´r·v±vÓ+>ÄÇÁÕ+GÓHÐHr   c               ó   € V ^8„  d   QhRR/# )r   r	   úset[int]r   )r   s   "r   r   r   £   s   € ÷ ñ �hñ r   c                 ó  € ^ RI p \        4       p V P                  4       pVe?   VP                  V9  d.   VP	                  VP                  4       VP                  4       pKB  V#   T P                  \        3 d     T# i ; i)zOThis process and its ancestors: never reap the shell that is running the prune.N)ÚpsutilÚsetÚProcessÚpidÚaddr1   ÚErrorr3   )rz   ÚpidsÚprocs      r   Ú_own_lineager‚   £   sr   € ãä“U€DðØ�~‰~ÓˆØÒ 4§8¡8°4Ô#7Ø�H‰H�T—X‘XÔØ—;‘;“=ŠDð €Køð �L‰Lœ'Ð"ô ØØ€Kðús   �AA$ Á$A?Á>A?c               ó    € V ^8„  d   QhRRRR/# )r   Úhomer   r	   rx   r   )r   s   "r   r   r   ²   s   € ÷ )ñ ) ð )¨ñ )r   c                ó   € ^ RI p^ RIHp ^ RIHp V! V R7      pVR,          R3.pYPV0 Uu. uF  qfR,          R3NK  	  up,          p\        4       pV EFn  w  r‰ \        P                  ! VP                  R	R
7      4      p
\        T
\        4      '       d   T
M.  EF"  p\        T\        4      '       d#   TP                  R4      TP                  T	4      3MRw  rÍ\        T\        4      '       d   T^ 8:  g   TP                  RR4      R8w  d   Kv  TP                  R4      R8X  d   T! T4      RJ d   Kš   Tf   TP!                  T4      pMUT	R8X  d=   \#        TP%                  T4      P'                  4       \)        T4      ,
          4      R8  pM^ RIHp T! T4      T8H  p T'       g   EK  TP3                  T4       EK%  	  EKq  	  V# u upi   \        \        3 d     EK�  i ; i  TP.                  \        \0        \        3 d     EKq  i ; i)a4  Live pids Hermes registered for *home*: the machine spawn ledger (every long-lived entry
point and MCP helper, ``hermes_cli.process_identity``) and the background-process checkpoint
(``tools.process_registry``, ``processes.json``). A recorded start time that no longer
matches is a reused pid, not ownership.N)Úspawner_is_dead)Úget_default_hermes_root)r„   zspawn-ledger.jsonÚcreate_timezprocesses.jsonÚhost_start_timeú	utf-8-sig)r-   r}   Ú	pid_scopeÚhostÚpurposez
mcp-helperTg       @)Úget_process_start_time)NN)rz   Úhermes_cli.process_identityr†   Úhermes_constantsr‡   r{   ÚjsonÚloadsÚ	read_textr3   Ú
ValueErrorÚ
isinstanceÚlistÚdictÚgetrD   Ú
pid_existsÚabsr|   rˆ   r[   Úgateway.statusrŽ   r   Ú	TypeErrorr~   )r„   rz   r†   r‡   rq   ÚsourcesÚbaser€   rC   Ú	stamp_keyÚentriesÚentryr}   ÚstampÚaliverŽ   s   &               r   Ú_registered_live_pidsr¤   ²   sÑ  € ó
 å;Ý8á"¨Ô-€DØÐ*Õ*¨MÐ:Ð;€GØÐPTÉÓVÉÀÐ(Õ(Ð*;Ó<ÉÑVÕV€GÜ“U€DÜ"‰ˆð	Ü—j’j §¡¸ Ó!EÓFˆGô !+¨7´D× 9Ò 9‘W¸rÓAˆEÜEOÐPUÔW[×E\ÒE\˜%Ÿ)™) EÓ*¨E¯I©I°iÓ,@ÑAÐbn‰JˆCÜ˜c¤3×'Ò'¨3°!¬8°u·y±yÀÈfÓ7UÐY_Ô7_Ùð �y‰y˜Ó# |Ô3¹ÈÓ8NÐRVÓ8VÙð
Ø’=Ø"×-Ñ-¨cÓ2‘EØ -Ô/Ü §¡¨sÓ 3× ?Ñ ?Ó AÄEÈ%ÃLÕ PÓQÐTWÑW‘EåEá2°3Ó7¸5Ñ@‘E÷ ŠuØ—‘˜—ô+ Bñ #ð6 €Kùò; Wøô
 œÐ$ô 	Ûð	ûð( —L‘L¤'¬9´jÐAô Ûðús6   ¬G	Á&GÄ6G'ÅAG'ÆG'ÇG$Ç#G$Ç'!HÈHc               ó    € V ^8„  d   QhRRRR/# )r   Ú
registeredrx   r	   rm   r   )r   s   "r   r   r   Þ   s   € ÷ 
ñ 
 xð 
°Dñ 
r   c                ó$  a€ ^ RI p V P                  S9   ;'       gW    \        ;QJ d-    V3R lV P                  4        4       F  '       g   K   R# 	  R# ! V3R lV P                  4        4       4      #   TP                  \
        3 d     R# i ; i)zÓRegistered itself, or a descendant of a live registered process (a background shell's
child). An orphan whose spawning shell is gone was reparented away from that lineage, so
it is not owned and is still reaped.Nc              3  ón   <"  € T F*  qP                   S9   ;'       d    VP                   ^8g  x € K,  	  R# 5i)é   N)r}   )Ú.0Úpr¦   s   & €r   Ú	<genexpr>Ú#_owned_by_hermes.<locals>.<genexpr>æ   s.   øé € Ð,hÑYgÐTU¯U©U°jÑ-@×-OÐ-OÀQÇUÁUÈaÁZÔ-OÓYgùs   ƒ5�5TF)rz   r}   Úanyr'   r   r3   )r�   r¦   rz   s   &f r   Ú_owned_by_hermesr¯   Þ   sv   ø€ ó ðà�x‰x˜:Ñ%×hÐh¯«Ô,hÐY]×YeÑYeÔYgÓ,h¯¬ÐhªÐh¨Ô,hÐY]×YeÑYeÔYgÓ,hÓ)hÐhøØ�L‰Lœ'Ð"ô Úðús-   ‡A4 �A4 ©"A4 ÁA4 ÁA4 ÁA4 Á4BÂBc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úscratch_rootr   Údoomedz
list[Path]r?   r%   r	   rD   r   )r   s   "r   r   r   ë   s/   € ÷ Iñ I¨4ð I¸ð IÈNð IÐhkñ Ir   c                óD
  a€ ^ RI p\        P                  P                  \	        V 4      4      pV Uu. uF+  p\        P                  P                  \	        V4      4      NK-  	  pp\        4       p\        \        R4      '       d   \        P                  ! 4       MRp. p	. p
VP                  R.4       EF  p Ve"   VP                  4       P                  V8w  d   K*  VP                  4       pT'       g   KD  TP                  R4      pT'       d   TR\        R4      )  MTo\!        ST4      '       g   K‚  T'       gh   \        P                  P#                  S4      '       dC   \$        ;QJ d    T3R lT 4       F  '       g   K   RM	  RM! T3R lT 4       4      '       g   Kñ  TP&                  T9   d   T
MT	P)                  TS34       EK  	  V	'       d7   \+        \-        V 4      P/                  4       P0                  P0                  4      M	\3        4       pY© UUu. uF  w  r¿\5        W¾4      '       g   K  W¿3NK  	  upp,           pV F­  w  poV Uu. uF?  p\!        S\        P                  P                  \	        V4      4      4      '       g   K=  VNKA  	  up FW  pVP7                  V4        VP9                  4       pVP;                  R	\        P<                  ! V4      VP&                  V4       KY  	  K¯  	  V	 UUau. uF|  w  poVS3V9  g   K  \        P                  P#                  S4      '       dC   \$        ;QJ d    V3R
 lV 4       F  '       g   K   RM	  RM! V3R
 lV 4       4      '       g   Kx  VS3NK~  	  p	ppV	'       g   ^ # V	 FE  w  po VP9                  4       pVP?                  4        TP;                  RTP&                  TS4       KG  	  TPA                  V	 UUu. uF  w  ppVNK
  	  upp\B        R7      w  ppV FQ  p VPE                  4       VPF                  8X  d   K%  VPI                  4        TP;                  RTP&                  4       KS  	  \J        P;                  R\        V	4      4       \        V	4      # u upi   TP                  \        3 d     EK÷  i ; iu uppi u upi   TP                  \        3 d    Rp ELi ; iu uppi   TP                  \        3 d     EKi  i ; iu uppi   TP                  \        3 d     EK  i ; i)a,  TERM (then KILL) same-user processes whose cwd is inside an entry about to be
pruned, or is a path under *scratch_root* that no longer exists. Returns the count.

Only the cwd is consulted: a process merely holding a file open inside scratch (an
editor, a log tail) is not ours to kill, but one *living* in a directory we are
about to delete, or in one already gone, has nothing left to run for.

A process Hermes owns (:func:`_owned_by_hermes`) is never signalled; each doomed entry it
works inside is dropped from *doomed* in place and recorded as kept.
NÚgetuidr}   z
 (deleted)c              3  ó<   <"  € T F  p\        SV4      x € K  	  R # 5ir   )rv   )rª   ÚtÚcwd_paths   & €r   r¬   Ú+reap_processes_rooted_in.<locals>.<genexpr>  s   øé € Ð9_ÑW^ÐRS¼&ÀÈ1×:MÐ:MÓW^ùs   ƒTFÚ?uG   scratch prune: kept %r â€” live Hermes process pid=%d (%r) works insidec           	   3  óˆ   <"  € T F7  p\        S\        P                  P                  \	        V4      4      4      x € K9  	  R # 5ir   )rv   rH   rC   ÚrealpathrM   )rª   Úer·   s   & €r   r¬   r¸     s4   øé € Ð7sÑlrÐgh¼¸xÌÏÉ×IYÑIYÔZ]Ð^_ÓZ`ÓIa×8bÐ8bÓlrùs   ƒ?Az.scratch prune: sent TERM pid=%d name=%r cwd=%r)Útimeoutz:scratch prune: sent KILL pid=%d (still running after TERM)z=scratch prune: reaped %d process(es) rooted in pruned entries)&rz   rH   rC   r»   rM   r‚   Úhasattrr´   Úprocess_iterÚuidsÚrealÚcwdr   r3   ÚendswithÚlenrv   Úexistsr®   r}   rQ   r¤   r   Úabsoluter1   r{   r¯   Úremover7   ÚinfoÚfspathÚ	terminateÚ
wait_procsÚ_REAP_GRACE_SECONDSÚstatusÚSTATUS_ZOMBIEÚkillr0   )r±   r²   r?   rz   rq   r«   ÚtargetsÚskipÚuidÚvictimsÚlineager�   rÂ   Údeletedr¦   r·   Úownedr¼   r¡   r7   Ú_r£   s   &&&            `      r   Úreap_processes_rooted_inrØ   ë   s  ø€ ó ä�7‰7×ÑœC Ó-Ó.€DÙ17Ó8±¨AŒr�w‰w×Ñ¤ A£Ö'±€GÐ8Ü‹>€DÜ ¤ X×.Ò.Œ"�)Š)Œ+°D€CØ02€Gð 13€GØ×#Ñ# U G×,ˆð	ØŠ 4§9¡9£;×#3Ñ#3°sÔ#:ÙØ—(‘(“*ˆC÷ ÙØ—,‘,˜|Ó,ˆß07�3Ð+œ#˜lÓ+Ð+Ñ,¸SˆÜ�h ×%Ò%Ùßœ"Ÿ'™'Ÿ.™.¨×2Ò2·c³cÔ9_ÑW^Ó9_·c·c²cÔ9_ÑW^Ó9_×6_Ô6_ØŸ™ DÔ(‰W¨g×=Ñ=¸tÀXÐ>N×Oñ -÷" X_Ô&¤t¨LÓ'9×'BÑ'BÓ'D×'KÑ'K×'RÑ'RÔSÔdgÓdi€JØ¸gÔl¹g©N¨DÔIYÐZ^×IkÔ'˜Ó'¹gÒlÕl€EÛ‰ˆˆhÙ!'ÓV¡˜A¬6°(¼B¿G¹G×<LÑ<LÌSÐQRËVÓ<T×+U—a�a¡ÔVˆEØ�M‰M˜%Ô ðØ—y‘y“{�ð �J‰JÐ`Ü—y’y Ó'¨¯©°4ö9ó Wñ  ñ 7>õ v±g¡N D¨(À$ÈÐAQÐY^ÑA^ÔÜŸ™Ÿ™ x×0Ò0·C³CÔ7sÑlrÓ7s·C·C²CÔ7sÑlrÓ7s×4sô  ��hÓ±g€Gñ vçÙÛ!‰ˆˆhð	Ø—9‘9“;ˆDØ�N‰NÔð 	�
‰
ÐCÀTÇXÁXÈtÐU]Ö^ñ "ð × Ñ ±gÔ!>±g©7¨4°£$±gÒ!>ÔH[Ð Ó\�H€A€uÛˆð	à�{‰{‹} × 4Ñ 4Ô4ÙØ�I‰IŒKð 	�
‰
ÐOÐQU×QYÑQYÖZñ ô ‡K�KÐOÔQTÐU\ÓQ]Ô^Üˆw‹<Ðùòw 9øð —‘œgÐ&ô 	Ûð	üó mùâVøð —L‘L¤'Ð*ô Ø“ðüóvøð —‘œgÐ&ô 	Ûð	üó "?øð —‘œgÐ&ô 	Ûð	ús›   ²1R	Â7#RÃRÈR-È5R-É:R3ÊR3Ê/R8Ë?SÌ$SÌ7
SÍSÍSÍ9SÎ SÏ)S=
ÐTÐ/TÒR*Ò)R*Ò8SÓSÓS:Ó9S:ÔTÔTc               ó    € V ^8„  d   QhRRRR/# )r   r¡   r   r	   úset[str]r   )r   s   "r   r   r   7  s   € ÷ ñ  $ð ¨8ñ r   c           	     óN  € \        4       p\        V 4      ^ 3.pV'       EdÉ   VP                  4       w  r4 \        P                  ! V4      ;_uu_ 4       pV EF„  pVP
                  R8X  Ed   VP                  RR7      '       dö    \        VP                  4      P                  RRR7      P                  4       pTP                  R4      '       d§   \        T\        R4      R P                  4       4      pTP                  P
                  R	8X  dd   TP                  P                  P
                  R8X  d<   TP                  \        TP                  P                  P                  4      4       EK  EK  EK   EK#  VP!                  RR7      '       g   EK>  V\"        8  g   EKL  VP
                  R
9  g   EK`  VP%                  VP                  V^,           34       EK‡  	  RRR4       EKÑ  V#   \         d     EK¥  i ; i  + '       g   i     EKø  ; i  \         d     EK
  i ; i)ziRepos whose linked worktrees live inside *entry* (``.git`` FILES, ``gitdir: <repo>/.git/worktrees/<n>``).z.gitFrF   rŠ   Úreplace)r-   r.   zgitdir:NÚ	worktrees)Únode_modulesz.venvÚvenv)r{   rM   rO   rH   rN   r7   ri   r   rC   r“   Ústripr3   rs   rÄ   r1   r~   rK   Ú_GIT_FILE_MAX_DEPTHrQ   )	r¡   ÚreposrS   rj   ÚdepthrT   rU   ÚlineÚgitdirs	   &        r   Ú_linked_worktree_reposræ   7  s   € ä“e€EÜ�%‹j˜!ˆ_Ð€Eß
ˆ%ØŸ™›‰ˆð	Ü—’˜G×$Ô$¨Ü�EØ—z‘z VÕ+°·±Èe°×0TÒ0Tð%Ü#'¨¯
©
Ó#3×#=Ñ#=À{Ð[dÐ#=Ó#e×#kÑ#kÓ#m˜Dð  Ÿ?™?¨9×5Ò5Ü%)¨$¬s°9«~¨Ð*?×*EÑ*EÓ*GÓ%H˜Fà%Ÿ}™}×1Ñ1°[Ô@ÀVÇ]Á]×EYÑEY×E^ÑE^ÐbhÔEhØ %§	¡	¬#¨f¯m©m×.BÑ.B×.IÑ.IÓ*J× Kò FiÒ@ò 6ð
 Ÿ™°e˜×<Õ<ÀÔI\×A\Ø %§
¡
Ð2S× SØŸ™ e§j¡j°%¸!µ)Ð%<×=ñ  ÷ %Ò$ð" €Løô  'ô %Û$ð%ú÷ %×$Ñ$ûô ô 	Ûð	úsl   µH Á0G?Â4G,Â9G?ÃB>G?ÆG?Æ"G?Æ6)G?ÇH Ç,G<	Ç7G?Ç;G<	Ç<G?Ç?H	È
H ÈH ÈH$È#H$c               ó    € V ^8„  d   QhRRRR/# )r   râ   rÚ   r	   r
   r   )r   s   "r   r   r   R  s   € ÷ Kñ K ð K¨dñ Kr   c                óZ  € \        V 4       F\  p\        P                  P                  V4      '       g   K*   \        P
                  ! RRVRR.\        P                  RRRR^RR	7       K^  	  R#   \        \        P                  3 d"   p\        P                  R
Y4        Rp?K™  Rp?ii ; i)zT``git worktree prune`` in each repo: drops registrations whose tree we just deleted.Úgitz-CÚworktreeÚpruneTr)   rÜ   F)ÚstdinÚcapture_outputÚtextr-   r.   r½   Úcheckz#git worktree prune in %s failed: %sN)ÚsortedrH   rC   ÚisdirÚ
subprocessÚrunÚDEVNULLr3   ÚSubprocessErrorr0   Údebug)râ   Úrepor>   s   &  r   Úrelease_git_worktreesrø   R  s�   € ä�u–ˆÜ�w‰w�}‰}˜T×"Ò"Ùð	KÜ�NŠNØ˜˜d J°Ð8Ü ×(Ñ(¸ÀDÐSZÐclØ %÷ó	 øô œ×3Ñ3Ð4ô 	KÜ�L‰LÐ>À×JÒJûð	Kús   ·1A.Á.B*Â	B%Â%B*c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   rq   r   Úmax_idle_hoursr[   Ú
skip_namesúfrozenset[str]r#   r$   r	   rD   r   )r   s   "r   r   r   a  s4   € ÷  ñ  Ø
ð Ø %ð Ø3Að ØMXð àñ r   c                óô   € \        V4      p \        WW$4      V\        Jd%   VP                   F  pVP	                  4        K  	  # #   T\        Jd%   TP                   F  pTP	                  4        K  	  i i ; i)aH  Delete top-level entries of *root* with no write anywhere in their subtree for
*max_idle_hours*, reaping processes and worktree registrations rooted in them first.
Each removal, each signalled process and each entry rescued mid-prune (touched
again after selection) is recorded in *log_file*. Returns the count actually
removed.)rA   Ú_prune_idle_entriesr0   ÚhandlersÚclose)rq   rú   rû   r#   r?   r@   s   &&&&  r   Úprune_idle_entriesr  a  sf   € ô ˜HÓ%€Eð Ü" 4¸ÓKàœÓØ Ÿ>œ>�Ø—‘–ò *ð øˆ5œÓØ Ÿ>œ>�Ø—‘–ò *ð ús   �A Á0A7c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   rq   r   rú   r[   rû   rü   r?   r%   r	   rD   r   )r   s   "r   r   r   r  s;   € ÷ gñ gØ
ðgØ %ðgØ3AðgØJXðgàñgr   c                óv  € \         P                   ! 4       VR ,          ,
          pV\        P                  ! V 4      ,          \        P                  \        P                  0,          p V P                  4        Uu. uF  qUP                  V9  g   K  VNK  	  pp. pT Fj  p\        YT4      w  r‰T\        8X  d   TP                  T4       K.  T	f   K4  \        P                  ! 4       '       g   KQ  \        P                  ! YT	.T4       Kl  	   \        YT4       T'       g   ^ # \#        4       p^ pT EFÖ  pTP%                  4       '       d)   TP'                  4       '       g   T\)        T4      ,          p\+        T4      p\-        YÔ4      pT\        8w  d¤    \.        P0                  ! T4       RpT'       d(   TP5                  R\.        P6                  ! T4      4       MXT\8        8X  d(   TP5                  R\.        P6                  ! T4      4       M&TP5                  R\.        P6                  ! T4      4       EK  . p TP%                  4       '       d.   TP'                  4       '       g   \        P:                  ! T4      pMTP=                  4          \.        P0                  ! T4       T'       d5   \        P                  ! 4       '       d   \        P                  ! YTT4       M&TP5                  R
\.        P6                  ! T4      4       EKÙ  	  \?        T4       T# u upi   \         d     ^ # i ; i  \         d$   p
\        P!                  RT
RR7        Rp
?
EL@Rp
?
ii ; i  \2         d    Rp ELÄ\         d    Rp ELÓi ; i  \         d4   p
TP5                  R	\.        P6                  ! T4      T
4        Rp
?
EKŒ  Rp
?
ii ; i  \2         d     M8\         d,    TP5                  R\.        P6                  ! T4      4        EKÕ  i ; iTP5                  R\.        P6                  ! T4      T4       T^,          pEK  )i  Nz'scratch prune: process reap skipped: %sT)Úexc_infoFz0scratch prune: entry %r vanished since selectionu;   scratch prune: rescued %r â€” touched since selection, keptuB   scratch prune: kept %r â€” activity re-scan failed, left untouchedz&scratch prune: could not remove %r: %sz(scratch prune: could not fully remove %rz.scratch prune: could not confirm removal of %rz$scratch prune: removed %r (%d bytes)) Útimerf   Ú
load_skipsÚSTUCK_STATE_NAMEÚSTUCK_LOCK_NAMEÚiterdirr7   r3   r]   rd   rQ   Útracking_supportedÚrecordrØ   Ú	Exceptionr0   rö   r{   rK   rL   ræ   rV   r_   rH   rI   r   rÈ   rÉ   rc   Ú#rmtree_collecting_permission_errorsÚunlinkrø   )rq   rú   rû   r?   rZ   r¼   r    r²   ÚstateÚ
denied_dirr>   râ   Úremovedr¡   ÚsizeÚ
entry_goneÚdenieds   &&&&             r   rþ   rþ   r  sB  € ô �YŠY‹[˜>¨DÕ0Õ0€Fð œe×.Ò.¨tÓ4Õ4¼×8NÑ8NÔPU×PeÑPeÐ7fÕf€JðØ"Ÿl™lœnÓI™n˜·±¸jÑ0H—1�1™nˆÐIð €FÛˆÜ)¨!Ó4ÑˆØ”EŒ>Ø�M‰M˜!ÖØÔ#¬×(@Ò(@×(BÔ(Bô �LŠL˜ : ,°Ö6ñ ðTÜ  ¨uÔ5÷ ÙÜ“e€EØ€GÜˆð �<‰<�>Š> %×"2Ñ"2×"4Ò"4ØÔ+¨EÓ2Õ2ˆEô ˜5Ó!ˆÜ# EÓ2ˆØ”EŒ>ð#Ü—’˜”Ø"�
÷
 Ø—
‘
ÐMÌrÏyÊyÐY^ÓO_Õ`Øœ(Ô"Ø—
‘
ØQÜ—I’I˜eÓ$õð
 —
‘
ØXÜ—I’I˜eÓ$ôò Øˆð	Ø�|‰|�~Š~ e×&6Ñ&6×&8Ò&8Ü×BÒBÀ5ÓI‘à—‘•ð	Ü�HŠH�UŒOßœ%×2Ò2×4Ò4Ü—’˜T¨&°%Õ8à—
‘
ÐEÄrÇyÂyÐQVÓGWÔXÚñA ôP ˜%Ô Ø€Nùò JøÜô Úðûô ô TÜ�‰Ð>ÀÈdˆ×SÒSûðTûôB %ô "Ø!“
Üô #Ø"“
ð#ûô* ô 	Ø�J‰JÐ?ÄÇÂÈ5ÓAQÐSVÔWÞûð	ûô !ô 	ÙÜô 	Ø�J‰JÐGÌÏÊÐSXÓIYÔZÛð	úð 	�
‰
Ð9¼2¿9º9ÀUÓ;KÈTÔRØ�1�‹s´   Á'L Á9LÂLÂL ÄL. ÆMÈ8NÉNÉ$NÉ;NÊOÊ+OË?OÌL ÌL+Ì*L+Ì.MÌ9MÍMÍM?Í/M?Í8M?Í>M?ÎO Î'N;Î;O ÏPÏPÏ'PÐPi  P r   ))r   Ú
__future__r   r   r‘   r5   rH   Úshutilrò   r  Úlogging.handlersr   Úpathlibr   Úhermes_constants_scratch_stuckrf   Ú	getLoggerr   r0   rÌ   rá   r9   r:   r   rA   rV   rc   re   rd   r_   r]   ro   rv   r‚   r¤   r¯   rØ   ræ   rø   r  rþ   r   r   r   Ú<module>r     sÊ   ðñ
õ #ã Û Û Û 	Û Û Û Ý 0Ý ã .à	×	Ò	˜8Ó	$€ð Ð àÐ ð 'Ð ØÐ ô
!Ð*ô !õõ:ð, €Ø€Ø€õ*õõ:
6õIõõ)õX
ð ^d÷ IõXõ6K÷ ÷"gr   