+
    iHàjû  ã                  ó   a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RI	H	t	H
t
Ht ^ RIHt ^ RIHt ^ RIHtHt Rt]P,                  ! 4       t]! 4       tR	]R
&   R R ltR R ltR R ltRR R lltR R ltR R lt R R lt!R R lt"R# )u>  Global emergency stop (ESTOP) â€” a resumable pause for NEW work only.

``hermes pause`` writes a sentinel at ``$HERMES_HOME/ESTOP``; ``hermes resume``
removes it. While it exists the cron scheduler, kanban dispatcher and new gateway
turns skip work; in-flight work is never killed. The check is one or two uncached
``os.stat`` calls (process home + fleet root when they differ). The body is optional
JSON ``{"reason", "engaged_at"}``; a corrupt/empty file still counts as engaged
(fail safe, e.g. ``touch ~/.hermes/ESTOP``). Ported from gastownhall/gastown estop.go (MIT).
)ÚannotationsN)Úsuppress)ÚdatetimeÚtimezoneÚUTC)ÚPath)ÚOptional)Ú_hermes_home_pathÚ_hermes_root_pathÚESTOPzset[str]Ú_logged_componentsc               ó   € V ^8„  d   QhRR/# )é   Úreturnr   © )Úformats   "Ú0/home/ubuntu/.hermes/hermes-agent/agent/estop.pyÚ__annotate__r      s   € ÷ *ñ *�tñ *ó    c                 ó,   € \        4       \        ,          # )zFPath of the ESTOP sentinel this process would write on `hermes pause`.)Ú_hermes_homeÚSENTINEL_NAMEr   r   r   Úsentinel_pathr      s   € ä‹>œMÕ)Ð)r   c               ó   € V ^8„  d   QhRR/# )r   r   Úlistr   )r   s   "r   r   r   $   s   € ÷ 6ñ 6 4ñ 6r   c                 óô   € \        4       p  \        4       \        ,          p TP	                  4       T P	                  4       8g  pT'       d   Y.# T .#   \         d    T .u # i ; i  \         d    Y8g  p L3i ; i)z®Profile home first, then the fleet root if it is a different directory: a profile
gateway (HERMES_HOME=~/.hermes/profiles/<n>) must still honor an operator's ~/.hermes/ESTOP.)r   Ú_canonical_rootr   Ú	ExceptionÚresolve)ÚprimaryÚrootÚdistincts      r   Ú_candidate_sentinel_pathsr"   $   s|   € ô ‹o€GðÜÓ ¤=Õ0ˆð#Ø—<‘<“> W§_¡_Ó%6Ñ6ˆ÷ 'ˆGˆ?Ð5¨W¨IÐ5øô ô ØˆyÒðûô ô #à‘?Šð#ús"   ŒA ¢!A% ÁA"Á!A"Á%A7Á6A7c               ó   € V ^8„  d   QhRR/# ©r   r   Úboolr   )r   s   "r   r   r   4   s   € ÷ 	ñ 	�Dñ 	r   c                 óˆ   € Rp \        4        F  p VP                  4       '       d    R# K  	  V #   \         d    Rp  K3  i ; i)zGTrue if ANY candidate sentinel exists; fail SAFE (True) on stat errors.FT)r"   ÚexistsÚOSError)Úsaw_stat_errorÚpaths     r   Ú
is_engagedr+   4   sJ   € à€NÜ)Ö+ˆð	"Ø�{‰{�}Š}Úñ ñ ,ð Ðøô ô 	"Ø!‹Nð	"ús   ‘0°AÁ Ac               ó    € V ^8„  d   QhRRRR/# )r   ÚreasonúOptional[str]r   r   r   )r   s   "r   r   r   @   s   € ÷ 
ñ 
�=ð 
¨Dñ 
r   c                óÔ  € \        4       pR\        P                  ! \        4      P	                  4       RT ;'       g    R/p VP
                  P                  RRR7       VP                  \        P                  ! V^R7      R,           RR	7       V#   \         dL    \        \        4      ;_uu_ 4        TP                  RR
7       RRR4        T#   + '       g   i      T# ; ii ; i)zDCreate the ESTOP sentinel. Idempotent; re-engaging updates the file.Ú
engaged_atr-   NT)ÚparentsÚexist_ok)ÚindentÚ
zutf-8©Úencoding)r2   )r   r   Únowr   Ú	isoformatÚparentÚmkdirÚ
write_textÚjsonÚdumpsr(   r   Útouch)r-   r*   Úpayloads   &  r   Úengager@   @   s¸   € ä‹?€DØœXŸ\š\¬#Ó.×8Ñ8Ó:¸HÀfÇnÀnÐPTÐU€Gð&Ø�‰×Ñ $°ÐÔ6Ø�‰œŸ
š
 7°1Ô5¸Õ<ÀwˆÔOð €Køô ô &Ü”g×ÕØ�J‰J ˆJÔ%÷ Ðà€K÷ ×à€Kúð&ús+   ÁAB Â"C'Â3CÃC'ÃC#ÃC'Ã#C'c               ó   € V ^8„  d   QhRR/# r$   r   )r   s   "r   r   r   M   s   € ÷ 	ñ 	�4ñ 	r   c                 ó‚   € Rp \        4        F  p VP                  4        Rp K  	  V #   \        \        3 d     K0  i ; i)z=Remove every visible sentinel (process-local and fleet-root).FT)r"   Úunlinkr(   ÚAttributeError)Úliftedr*   s     r   Ú	disengagerF   M   sG   € à€FÜ)Ö+ˆð	Ø�K‰KŒMØŠFñ ,ð €Møô œÐ(ô 	Úð	ús   ‘)©>½>c               ó   € V ^8„  d   QhRR/# )r   r   zOptional[dict]r   )r   s   "r   r   r   Y   s   € ÷ $ñ $�>ñ $r   c            	     ój  € \        4       '       g   R# RRRR/p Rp\        4        FÉ  p VP                  4       '       g   K   Rp\        \        \        \        4      ;_uu_ 4        \        P                  ! TP                  RR7      4      p\        T\        4      '       dD   RTP                  R4      ;'       g    RRTP                  R4      ;'       g    R/p  RRR4        M RRR4       KË  	  V'       d   V # R#   \         d    T u u # \         d     K÷  i ; i  + '       g   i     EK  ; i)z…Return ``{"reason", "engaged_at"}`` or None when not engaged; an unreadable/corrupt
body still reports engaged with both fields None.Nr-   r0   FTz	utf-8-sigr5   )r+   r"   r'   r(   rD   r   Ú
ValueErrorr<   ÚloadsÚ	read_textÚ
isinstanceÚdictÚget)ÚstateÚfoundr*   Úraws       r   Ú	get_staterR   Y   s  € ô �<Š<ÙØ�t˜\¨4Ð0€EØ€EÜ)Ö+ˆð	Ø—;‘;—=’=Ùð !ð ˆÜ”gœz¬>×:Õ:Ü—*’*˜TŸ^™^°[˜^ÓAÓBˆCÜ˜#œt×$Ò$Ø! 3§7¡7¨8Ó#4×#<Ð#<¸¸lÈCÏGÉGÐT`ÓLa×LiÐLiÐeiÐj�Ø÷	 ;Ñ:à$÷ ;Ñ:ñ ,÷ ˆ5Ð#˜tÐ#øô ô 	ØŒLÜô 	Úð	ú÷ ;×:Ñ:ús6   ©C>Á%AD Â;D ÃD Ã>DÄDÄDÄDÄ D2c               ó   € V ^8„  d   QhRR/# )r   r   r.   r   )r   s   "r   r   r   q   s   € ÷ mñ m�mñ mr   c                 óz   € \        4       p V f   R# V P                  R4      '       d   RV R,           R2MRpRV R2# )zFShort user-facing notice for new gateway turns, or None if not paused.Nr-   z (Ú)Ú u   â�¸ï¸� Hermes is pausedzB. New work is on hold; run `hermes resume` to pick things back up.)rR   rN   )rO   Útags     r   Úpaused_replyrX   q   sD   € ä‹K€EØ‚}ÙØ%*§Y¡Y¨x×%8Ò%8ˆBˆu�X�Ð˜qÑ
!¸b€CØ$ S EÐ)kÐlÐlr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Ú	componentÚstrÚloggerzlogging.Loggerr   r%   r   )r   s   "r   r   r   z   s!   € ÷ ñ ˜Cð ¨ð ¸Dñ r   c                óæ  € \        4       '       g/   \        ;_uu_ 4        \        P                  V 4       RRR4       R# \        ;_uu_ 4        V \        9  p\        P	                  V 4       RRR4       X'       dO   \        4       ;'       g    / P                  R4      pV'       d   RV R2MRpVP                  RW\        4       4       R#   + '       g   i     R# ; i  + '       g   i     L|; i)	z^Return True when engaged, logging once per engagement per component (re-armed after a resume).NFr-   z
 (reason: rU   rV   uR   %s dispatch paused by global emergency stop%s â€” remove with `hermes resume` (%s)T)	r+   Ú	_log_lockr   ÚdiscardÚaddrR   rN   Úinfor   )rZ   r\   Úfirstr-   Úsuffixs   &&   r   Úcheck_pausedrd   z   s¤   € ä�<Š<ßŽYÜ×&Ñ& yÔ1÷ áß	ŽØÔ!3Ñ3ˆÜ×Ñ˜yÔ)÷ 
÷ Ü“+×#Ð# ×(Ñ(¨Ó2ˆß+1�:˜f˜X QÑ'°rˆØ�‰Ø`Øœ}›ô	
ñ ÷ ŽYáúß	�ús   ŸCÁC ÃC	Ã C0	)N)#Ú__conditional_annotations__Ú__doc__Ú
__future__r   r<   ÚloggingÚ	threadingÚ
contextlibr   r   r   r   Úpathlibr   Útypingr   Úagent.file_safetyr	   r   r
   r   r   ÚLockr^   Úsetr   Ú__annotations__r   r"   r+   r@   rF   rR   rX   rd   )re   s   @r   Ú<module>rq      sw   øðôõ #ã Û Û Ý ß ,Ñ ,Ý Ý ÷ fà€ð �NŠNÓ€	Ù"›uÐ �HÓ $õ*õ
6õ 	÷
õ	õ$õ0m÷r   