+
    jHàj8˜ ã            ,       ó€
  a € ER< tË0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	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HtHt ^ RIHt ^ RIHtHtHtHt ^ RIHt ^ RIH t H!t!H"t" ^ RI#H$t$H%t%H&t& ^ R	I'H(t( ^ R
I)H*t*H+t+ ^ RI,H-t- ]P\                  R8X  d   ^ RI/t/M^ RI0t0Rt1Rt2Rt3]P\                  R8H  t4]5! 4       t6Rt7Rt8ER=t9Rt:]Pv                  ! 4       t</ t=] ^ k ]P|                  ! ]?4      t@ ! R R4      tA]P„                  ! 4       tCRsD] ^k RsE] ^k R R ltFRsG] ^k R R ltHER>R R lltIER>R R lltJ ! R R]4      tKER?RR /R! R" llltLR# R$ ltMR% R& ltNR' R( ltOR)R/R* R+ lltP]
P¢                  ! R,4      tRR- R. ltSR/ R0 ltTR1 R2 ltUER@R3 R4 lltVR5 R6 ltWR7 R8 ltXR9 R: ltYR;tZR< R= lt[]\! R>R?04      t]R@ RA lt^RBRCRDR/RE RF llt_RG RH lt`^Èta]a3RI RJ lltbRK RL ltcRM RN ltdRO RP lteRQ RR ltfRS RT ltgRU RV lthRW RX ltiRY RZ ltjR[ R\ ltkR] R^ ltlR_ R` ltmRa Rb ltnRc Rd lto]
P¢                  ! Re4      tpRf Rg ltqRh Ri ltrRj Rk ltsRl Rm lttR)R/Rn Ro lltuRp Rq ltvRr Rs ltwRt Ru ltxRv Rw ltyRx Ry ltzRzRC/R{ R| llt{R} R~ lt|R R€ lt}ER@R� R‚ llt~ER@Rƒ R„ lltERAR… R† llt€R‡ Rˆ lt�R‰ RŠ lt‚R‹ RŒ ltƒR� RŽ lt„R�R�/R‘ R’ l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‹RŸ R  ltŒER@R¡ R¢ l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“R¯]6R°]6R±]6R²]6R³]6R´]6Rµ]6R¶]6R·]6R¸]6R¹]6Rº]6R»]6R¼]6R½]6R¾]6R¿]6RÀ]6RÁRCRÂRRÃR�RÄRC/RÅ RÆ llt”RÇ RÈ lt•RÄRCRÉR/RÊ RË llt–RÌ RÍ lt—ER@RÎ RÏ llt˜^xt™]™3RÐ RÑ lltšRÒ RÓ lt›RÔ RÕ ltœRÖ R× lt�]\! RØRÙ04      tžRÚ RÛ ltŸRÜ RÝ lt ]! R�RÞ7       ! Rß Rà4      4       t¡Rá Râ lt¢Rã Rä lt£Rå Ræ lt¤Rç Rè lt¥RéRRê]6RëRRìR�RíRRîRRïR/Rð Rñ llt¦ER@R)R/Rò Ró lllt§Rô Rõ lt¨Rö R÷ lt©Rø Rù ltªER@Rú Rû llt«Rü Rý lt¬Rþt­^<t®Rÿt¯^<t°ER@ER  ER llt±ER ER lt²ER ER lt³ER ER lt´ER ER	 ltµER
RERRC/ER ER llt¶ERRER]6/ER ER llt·ER ER lt¸ER ER lt¹ER@ER ER lltºER ER lt»ER ER lt¼ER ER lt½ER ER lt¾ER ER!/ER" ER# llt¿ER$^ER%^/ER& ER' lltÀER( ER) ltÁER* ER+ ltÂRtÃER, ER- ltÄER. ER/ ltÅER0 ER1 ltÆER2 ER3 ltÇER@ER4R�/ER5 ER6 llltÈER7 ER8 ltÉER@ER4R�ER9]:/ER: ER; llltÊR# (B  z™Gateway runtime status helpers: PID/lock/marker files under ``{HERMES_HOME}`` (one set per
home/profile) that tell whether the gateway daemon is running.N)Ú	dataclass)ÚdatetimeÚtimezoneÚUTC©ÚPath)ÚAnyÚCallableÚ
NamedTupleÚOptional)Úmake_user_dir)Úcommand_line_runs_inline_sourceÚinline_bootstrap_argvÚinline_source_flag_index)Ú!_get_platform_default_hermes_homeÚget_hermes_homeÚget_process_hermes_home)Úpid_exists_stdlib)Úunusable_lock_dirÚunusable_lock_dir_recovered©Úatomic_json_writeÚwin32úhermes-gatewayúgateway_state.jsonzgateway-lockszgateway.lockg      ð?c                   óœ   a € ] tR t^:t o RtRV 3R lR lltV 3R lR ltRV 3R lR lltRV 3R	 lR
 lltV 3R lR lt	V 3R lR lt
RtV tR# )Ú_RuntimeStatusWritera  Persist the latest complete status snapshot on one daemon thread.

Runtime status is diagnostic state, not an event log. While one write is
blocked in filesystem I/O, newer submissions replace the single pending
snapshot. This bounds memory and keeps every status producer off asyncio.
Nc                ó`   <€ V ^8„  d   QhRS[ S[S[S[S[S[3,          .R3,          ,          /# )é   Úwrite_fnN)r   r	   r   ÚdictÚstrr   )ÚformatÚ__classdict__s   "€Ú3/home/ubuntu/.hermes/hermes-agent/gateway/status.pyÚ__annotate__Ú!_RuntimeStatusWriter.__annotate__B   s0   ø€ ÷ 
8ñ 
8¡©(±D¹$¹sÁC¸x½.Ð3IÈ4Ð3OÕ*PÕ!Qñ 
8ó    c                ó¶   € Wn         \        P                  ! 4       V n        R V n        ^ V n        ^ V n        ^ V n        ^ V n        R V n	        RV n
        R V n        R # )NF)Ú	_write_fnÚ	threadingÚ	ConditionÚ
_conditionÚ_pendingÚ_writing_generationÚ_submitted_generationÚ_completed_generationÚ_successful_generationÚ_last_errorÚ_failure_loggedÚ_thread)Úselfr   s   &&r$   Ú__init__Ú_RuntimeStatusWriter.__init__B   sU   € Ø!ŒÜ#×-Ò-Ó/ˆŒØDHˆŒØ#$ˆÔ Ø%&ˆÔ"Ø%&ˆÔ"Ø&'ˆÔ#Ø48ˆÔØ$ˆÔØ37ˆŽr'   c                óB   <€ V ^8„  d   QhRS[ RS[S[S[3,          RS[/# ©r   ÚpathÚpayloadÚreturn)r   r    r!   r   Úint)r"   r#   s   "€r$   r%   r&   N   s*   ø€ ÷ 
ñ 
™4ð 
©$©s±C¨x­.ð 
¹Sñ 
r'   c                ó  € V P                   ;_uu_ 4        V ;P                  ^,          un        V P                  pW1\        P                  ! V4      3V n        V P
                  e!   V P
                  P                  4       '       gC   \        P                  ! V P                  RRR7      V n        V P
                  P                  4        V P                   P                  4        VuuRRR4       #   + '       g   i     R# ; i)é   NTzgateway-runtime-status-writer)ÚtargetÚdaemonÚname)r,   r/   ÚcopyÚdeepcopyr-   r4   Úis_aliver*   ÚThreadÚ_runÚstartÚ
notify_all)r5   r:   r;   Ú
generations   &&& r$   ÚsubmitÚ_RuntimeStatusWriter.submitN   s¦   € Ø�_�_‹_Ø×&Ò&¨!Õ+Õ&Ø×3Ñ3ˆJØ'¬t¯}ª}¸WÓ/EÐFˆDŒMØ�|‰|Ò#¨4¯<©<×+@Ñ+@×+BÒ+BÜ(×/Ò/ØŸ9™9¨TÐ8Wô Y�”à—‘×"Ñ"Ô$Ø�O‰O×&Ñ&Ô(Ø÷ �_�_‹_ús   •A0C.ÂAC.Ã.C?	c                ó<   <€ V ^8„  d   QhRS[ RS[S[,          RS[/# )r   rJ   Útimeoutr<   )r=   r   ÚfloatÚbool)r"   r#   s   "€r$   r%   r&   Z   s&   ø€ ÷ ñ ™sð ©X±e­_ð Éñ r'   c                ó  € Vf   RM%\         P                  ! 4       \        VR4      ,           pV P                  ;_uu_ 4        V P	                  V4      ;pfm   Vf   V P                  P                  4        K5  V\         P                  ! 4       ,
          pV^ 8:  d    RRR4       R# V P                  P                  VR7       K�  V'       g   Vf   V P                  e   V P                  hVuuRRR4       #   + '       g   i     R# ; i)z\Block until ``generation`` (or a later snapshot) is persisted; ``False`` on timeout/failure.Nç        F©rN   )ÚtimeÚ	monotonicÚmaxr,   ÚsettledÚwaitr2   )r5   rJ   rN   ÚdeadlineÚstateÚ	remainings   &&&   r$   rX   Ú_RuntimeStatusWriter.waitZ   s½   € à"š?‘4´·²Ó0@Ä3ÀwÐPSÓCTÕ0TˆØ�_�_‹_Ø ŸL™L¨Ó4Ð4�5Ò=ØÒ#Ø—O‘O×(Ñ(Ô*ÙØ$¤t§~¢~Ó'7Õ7�	Ø ”>Ø ÷ ‰_ð —‘×$Ñ$¨YÐ$Ö7ß˜Wš_°×1AÑ1AÒ1MØ×&Ñ&Ð&Ø÷ �_�_‹_ús   ÁAC5Â%%C5ÃC5Ã5D	c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   rN   r<   ©rO   rP   )r"   r#   s   "€r$   r%   r&   j   s   ø€ ÷ Iñ I™Uð I©Tñ Ir'   c                ó¸   € V P                   ;_uu_ 4        V P                  pR R R 4       X^ 8H  ;'       g    V P                  W!R7      #   + '       g   i     L/; i)NrS   )r,   r/   rX   )r5   rN   rJ   s   && r$   ÚflushÚ_RuntimeStatusWriter.flushj   s@   € Ø�_�_‹_Ø×3Ñ3ˆJ÷ à˜Q‰×HÐH $§)¡)¨J )Ó"HÐH÷ �_ús   •A	Á	A	c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# )r   rJ   r<   )r=   r   rP   )r"   r#   s   "€r$   r%   r&   o   s   ø€ ÷ 
3ñ 
3¡#ð 
3©(±4­.ñ 
3r'   c                ó0  € V P                   ;_uu_ 4        V P                  V8¼  d    RRR4       R# V P                  V8¬  ;'       d&    V P                  ^ 8H  ;'       d    V P                  RJ pV'       d   RMRuuRRR4       #   + '       g   i     R# ; i)zW``True`` once ``generation`` persisted, ``False`` once it can no longer, else ``None``.NTF)r,   r1   r0   r.   r-   )r5   rJ   Úno_more_works   && r$   rW   Ú_RuntimeStatusWriter.settledo   s{   € à�_�_‹_Ø×*Ñ*¨jÔ8Ø÷ ‰_ð ×*Ñ*¨jÑ8÷ *ð *Ø×,Ñ,°Ñ1÷*ð *à—M‘M TÐ)ð ÷
 )‘5¨d÷ �_�_‹_ús"   •B²BÁBÁBÁ6BÂB	c                ó   <€ V ^8„  d   QhRR/# ©r   r<   N© )r"   r#   s   "€r$   r%   r&   {   s   ø€ ÷ Tñ T�dñ Tr'   c                ó¼  €  V P                   ;_uu_ 4        V P                  f   V P                   P                  4        K*  V P                  w  rpRV n        Wn        RRR4       Rp V P                  ;'       g    \
        ! X\        VX4      4       V P                   ;_uu_ 4        ^ V n        \        V P                  X4      V n	        Vf$   \        V P                  V4      V n
        RV n        MW@n        V P                   P                  4        RRR4       Vf5   V P                  '       d    \        P                  R4       RV n        EKM  EKP  V P                  '       g!   \        P!                  RV4       R V n        EK‚  \        P#                  RV4       EK›    + '       g   i     ELH; i  \         d   pTp Rp?EL0Rp?ii ; i  + '       g   i     LÂ; i)TNz,Gateway runtime-status persistence recoveredFzFFailed to persist gateway runtime status; later updates will retry: %sz,Failed to persist gateway runtime status: %s)r,   r-   rX   r.   r)   Ú_write_json_fileÚ_merge_over_on_diskÚBaseExceptionrV   r0   r1   r2   rI   r3   ÚloggerÚinfoÚwarningÚdebug)r5   rJ   r:   r;   ÚerrorÚexcs   &     r$   rG   Ú_RuntimeStatusWriter._run{   sh  € ØØ——“Ø—m‘mÒ+Ø—O‘O×(Ñ(Ö*Ø,0¯M©MÑ)�
 'Ø $�”Ø+5Ô(÷ !ð .2ˆEðØ—‘×3Ð3Ô#3Ð3°TÔ;NÈtÐU\Ó;]Ô^ð ——“Ø+,�Ô(Ü-0°×1KÑ1KÈZÓ-X�Ô*Ø’=Ü25°d×6QÑ6QÐS]Ó2^�DÔ/Ø'+�DÕ$à',Ô$Ø—‘×*Ñ*Ô,÷ !ð Š}Ø×'×'Ð'Ü—K‘KÐ NÔOØ+0�D×(ò (ð ×)×)Ð)Ü—‘Ø\Ð^côeà'+�×$ä—‘ÐKÈU×S÷; !—�ûô !ô Ø–ûðúç —ús7   –AFÁ(F0 Á;F0 Â'A*GÆF-	Æ0GÆ;GÇGÇG	)
r0   r,   r3   r2   r-   r/   r1   r4   r)   r.   ©N©ç       @)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r6   rK   rX   ra   rW   rG   Ú__static_attributes__Ú__classdictcell__©r#   s   @r$   r   r   :   sJ   ø‡ € ñ÷
8ò 
8÷
ð 
÷ò ÷ Iò I÷

3ð 
3÷Tö Tr'   r   c                ó€   € V ^8„  d   QhR\         R\        \        \        3,          R\        \        \        3,          /# r9   ©r   r    r!   r   )r"   s   "r$   r%   r%   ¢   s6   € ÷ Nñ Nœdð N¬T´#´s°(­^ð NÄÄSÌ#ÀXÅñ Nr'   c                óT   € \        V 4      p\        V\        4      '       d   / VCVC# T# )a  Lay the canonical snapshot over whatever is on disk right before writing. Out-of-process
writers (the migration's compensator clearing multiplex-owned status, container_boot
seeding ``desired_state``) stamp this file directly; the gateway's fields win, theirs survive.)Ú_read_json_fileÚ
isinstancer    )r:   r;   Úexistings   && r$   rl   rl   ¢   s0   € ô ˜tÓ$€HÜ&0°¼4×&@Ò&@Ð"ˆhÐ"˜'Ð"ÐMÀgÐMr'   c                ó$   € V ^8„  d   QhR\         /# ©r   r<   )r   )r"   s   "r$   r%   r%   ­   s   € ÷ &ñ &Ô$8ñ &r'   c                 óŒ   € \         ;_uu_ 4        \        f   \        4       s\        uuRRR4       #   + '       g   i     R# ; i)zULazily create the single writer; callers serialise on ``_runtime_status_state_lock``.N)Ú_runtime_status_state_lockÚ_runtime_status_writerr   ri   r'   r$   Ú_get_runtime_status_writerr‹   ­   s+   € ÷ 
$Ö	#Ü!Ò)Ü%9Ó%;Ð"Ü%÷ 
$×	#×	#Ó	#ús	   �2²A	rw   c                ó0   € V ^8„  d   QhR\         R\        /# r^   r_   )r"   s   "r$   r%   r%   ¶   s   € ÷ Eñ E¤%ð E´$ñ Er'   c                ó>   € \         pVf   R# VP                  V R7      # )z?Wait boundedly for all runtime-status updates submitted so far.TrS   )rŠ   ra   ©rN   Úwriters   & r$   Úflush_runtime_statusr�   ¶   s!   € ä#€FØ’>ˆ4ÐD v§|¡|¸G |Ó'DÐDr'   c                ó0   € V ^8„  d   QhR\         R\        /# r^   r_   )r"   s   "r$   r%   r%   ¼   s   € ÷ Sñ S¬eð S¼dñ Sr'   c              ƒ  ó    "  € \         pVf   R# \        P                  ! VP                  \	        \        V 4      R4      R7      G Rj  x€L
 #  L5i)zDAwait the current writer generation without blocking the event loop.NTrR   rS   )rŠ   ÚasyncioÚ	to_threadra   rV   rO   rŽ   s   & r$   Úflush_runtime_status_asyncr•   ¼   s:   é € ä#€FØ‚~Ùä×"Ò" 6§<¡<¼¼UÀ7»^ÈSÓ9QÔR×RÐRÑRùs   ‚AAÁAÁAc                   ó0   a € ] tR t^Åt o RtV 3R ltRtV tR# )Ú	StormInfozFRespawn-storm check result: start count, window, and backoff to sleep.c                ó>   <€ V ^8„  d   Qh/ S[ ;R&   S[;R&   S[;R&   # )r   ÚcountÚwindow_sÚ	backoff_s)r=   rO   )r"   r#   s   "€r$   r%   ÚStormInfo.__annotate__Å   s*   ø‡ ‚ ñ �Jñ ñ �Oñ	 ñ
 Ñò r'   ri   N)rx   ry   rz   r{   r|   Ú__annotate_func__r}   r~   r   s   @r$   r—   r—   Å   s   ø‡ € ÙP÷ ƒ r'   r—   Úbackoff_cap_sg     Àr@c          	      ó^   € V ^8„  d   QhR\         R\        R\        R\        \        ,          /# )r   Ú
max_startsrš   rž   r<   )r=   rO   r   r—   )r"   s   "r$   r%   r%   Í   s1   € ÷  ñ  Üð Ü#(ð ÜDIð äŒiÕñ r'   c          
     ó  €  \        4       R,          p\        VP                  RRR7       \        P                  ! \
        4      P                  4       p. pVP                  4       '       d]   VP                  RR7      P                  4        F8  pVP                  4       pV'       g   K   VP                  \        V4      4       K:  	  VP                  V4       V Uu. uF  qtV,
          V8:  g   K  VNK  	  ppV\        V ^,          ^(4      ) R p	VP                  R4      p
V
P!                  RP#                  R	 V	 4       4      R,           R
R7       \$        P&                  ! W£4       \)        V4      V 8:  d   R# \+        VR^\+        \)        V4      V ,
          ^4      ,          ,          4      p\-        \)        V4      WR7      #   \         d     EKF  i ; iu upi   \.         d"   p\0        P3                  RT4        Rp?R# Rp?ii ; i)z­Record this start; :class:`StormInfo` when > ``max_starts`` landed in ``window_s``.
Best-effort: a broken ``gateway-starts.log`` ledger is logged and swallowed, never fatal.zgateway-starts.logT©ÚparentsÚexist_okú	utf-8-sig©ÚencodingNz.tmpÚ
c              3   ó8   "  € T F  p\        V4      x € K  	  R # 5iru   )Úrepr)Ú.0Útss   & r$   Ú	<genexpr>Ú/record_start_and_check_storm.<locals>.<genexpr>å   s   é € Ð =±H¨b¤ b§ ³Hùó   ‚úutf-8ç      @)r™   rš   r›   z8respawn-storm breaker bookkeeping failed (non-fatal): %s)r   r   Úparentr   Únowr   Ú	timestampÚexistsÚ	read_textÚ
splitlinesÚstripÚappendrO   Ú
ValueErrorrV   Úwith_suffixÚ
write_textÚjoinÚosÚreplaceÚlenÚminr—   Ú	Exceptionrn   rq   )r    rš   rž   r:   r³   r…   Úliner¬   ÚrecentÚto_writeÚtmpÚbackoffÚ_es   &&$          r$   Úrecord_start_and_check_stormrÉ   Í   s�  € ð
ÜÓ Ð#7Õ7ˆÜ�d—k‘k¨4¸$Õ?Ü�lŠlœ3Ó×)Ñ)Ó+ˆØ "ˆØ�;‰;�=Š=ØŸ™°˜Ó<×GÑGÖI�Ø—z‘z“|�ßÙðØ—O‘O¤E¨$£KÖ0ñ Jð 	�‰˜ÔÙ'Ó@™x˜°­8°xÑ+?—"�"™xˆÐ@àœS ¨a¥°Ó4Ð4Ð5Ð6ˆØ×Ñ˜vÓ&ˆØ�‰�t—y‘yÑ =±HÓ =Ó=ÀÕDÈwˆÔWÜ
�
Š
�3ÔÜˆv‹;˜*Ô$ÙÜ�m S¨A´´S¸³[À:Õ5MÈqÓ1QÕ,QÕ%RÓSˆÜœs 6›{°XÔQÐQøô "ô Ûðüò Aøô ô Ü�‰ÐOÐQSÔTÝûðúsV   ‚B&G Â)GÃG ÃGÃ0GÃ6B G Å8A	G ÇGÇG ÇGÇG ÇHÇ%HÈHc                ó$   € V ^8„  d   QhR\         /# r‡   r   )r"   s   "r$   r%   r%   ð   s   € ÷ %ñ %¤$ñ %r'   c                 ó   € \        4       # )z¨Launch-home HERMES_HOME for identity files (PID, lock, status, markers):
``get_hermes_home()`` honors the per-session ``_HERMES_HOME_OVERRIDE`` and would misroute
them.)r   ri   r'   r$   Ú_get_process_hermes_homerÌ   ð   s   € ô #Ó$Ð$r'   c                óF   € V ^8„  d   QhR\         \        ,          R\         /# ©r   r:   r<   )r   r!   )r"   s   "r$   r%   r%   ÷   s   € ÷ 9ñ 9¤¬¥ð 9´ñ 9r'   c                óT   € \        V 4      P                  4       P                  RR7      # )z=Stable absolute HERMES_HOME path for persisted identity data.F)Ústrict)r   Ú
expanduserÚresolve©r:   s   &r$   Ú_canonical_hermes_homerÔ   ÷   s#   € ä�‹:× Ñ Ó"×*Ñ*°%Ð*Ó8Ð8r'   c                óh   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\        /# )r   ÚleftÚrightr<   ©r   r!   rP   )r"   s   "r$   r%   r%   ü   s.   € ÷ Jñ JœD¤3�Jð J¬t´c­zð J¼dñ Jr'   c                óÌ   € \         P                  P                  \        \	        V 4      4      4      pV\         P                  P                  \        \	        V4      4      4      8H  # )zBCompare HERMES_HOME paths with the host platform's case semantics.)r¾   r:   Únormcaser!   rÔ   )rÖ   r×   Úleft_cs   && r$   Ú_same_hermes_homerÜ   ü   sF   € ä�W‰W×ÑœcÔ"8¸Ó">Ó?Ó@€FØ”R—W‘W×%Ñ%¤cÔ*@ÀÓ*GÓ&HÓIÑIÐIr'   Úexpected_homec                ó    € V ^8„  d   QhR\         \        \        \        3,          ,          R\         \        \        ,          ,          R\
        /# )r   ÚrecordrÝ   r<   )r   r    r!   r   r   rP   )r"   s   "r$   r%   r%     s:   € ÷ ñ Ü”Tœ#œs˜(•^Õ$ðÜ8@ÄÌÅÕ8Lðä	ñr'   c               ó  € \        V \        4      '       d   V P                  R4      MRp\        V\        4      '       d   VP	                  4       '       g   R#  Ve   TM	\        4       p\        W#4      '       * #   \         d     R# i ; i)a(  True when a persisted gateway record names a DIFFERENT HERMES_HOME (cross-profile kill guard:
profile B's stop must never SIGTERM profile A). ``expected_home`` overrides the comparison base.
Legacy records without ``hermes_home`` prove nothing -> False; a comparison failure fails
closed -> True.Úhermes_homeNFT)r„   r    Úgetr!   r¸   rÌ   rÜ   rÂ   )rß   rÝ   Úrecorded_homeÚbases   &$  r$   Úrecorded_gateway_home_conflictsrå     ss   € ô 2<¸FÄD×1IÒ1I�F—J‘J˜}Ô-Èt€MÜ�m¤S×)Ò)°×1DÑ1D×1FÒ1FÙðØ -Ò 9‰}Ô?WÓ?YˆÜ$ ]Ó9Ô9Ð9øÜô Úðús   ÁA9 Á9BÂBz^[a-z0-9][a-z0-9_-]{0,63}$c                ó\   € V ^8„  d   QhR\         \        ,          R\        \        ,          /# ©r   Úhomer<   )r   r!   r   )r"   s   "r$   r%   r%     s"   € ÷ ñ ¤$¬¥*ð ´¼#µñ r'   c                óÜ  €  \        V 4      pTP                  P                  R8X  d2   \        P                  TP                  4      '       d   TP                  # ^ RIpTP                  \        3pT FQ  p\        P                  ! \        4      ;_uu_ 4        \        Y! 4       4      '       d    RRR4        R#  RRR4       KS  	  R#   \         d     R# i ; i  + '       g   i     Kz  ; i)zYBest-effort label: ``<root>/profiles/<name>`` -> name, root home -> "default", else None.NÚprofilesÚdefault)rÔ   rÂ   r²   rB   Ú_PROFILE_LABEL_REÚmatchÚhermes_constantsÚget_default_hermes_rootr   Ú
contextlibÚsuppressrÜ   )rè   Ú	canonicalrî   Údefault_homesÚdefault_homes   &    r$   Ú_profile_label_for_homerõ     s¿   € ðÜ*¨4Ó0ˆ	ð ×Ñ×Ñ 
Ô*Ô/@×/FÑ/FÀyÇ~Á~×/VÒ/VØ�~‰~ÐÛØ%×=Ñ=Ô?`Ða€MÛ%ˆÜ× Ò ¤×+Õ+Ü  ¨L«N×;Ò;Ø ÷ ,Ò+Ø;÷ ,Ñ+ñ &ñ øô ô Úðú÷ ,×+Ð+ús   ‚C ÂCÃCÃCÃC+c                ó~   € V ^8„  d   QhR\         \        \        \        3,          ,          R\         \        ,          /# ©r   rß   r<   ©r   r    r!   r   )r"   s   "r$   r%   r%   )  s/   € ÷ 	]ñ 	]¤H¬T´#´s°(­^Õ$<ð 	]ÄÌ#Åñ 	]r'   c                ó†  € \        V \        4      '       g   R# V P                  R4      p\        V\        4      '       d:   \        P                  VP                  4       4      '       d   VP                  4       # V P                  R4      p\        V\        4      '       d"   VP                  4       '       d   \        V4      # R# )z¶Profile label of a scoped-lock owner (None: PID-only wording): the validated ``profile``
field stamped by :func:`acquire_scoped_lock`, else inferred from ``hermes_home`` (old locks).NÚprofilerá   )r„   r    râ   r!   rì   rí   r¸   rõ   )rß   rú   rè   s   &  r$   Úscoped_lock_owner_labelrû   )  sˆ   € ô �fœd×#Ò#ÙØ�j‰j˜Ó#€GÜ�'œ3×ÒÔ$5×$;Ñ$;¸G¿M¹M»O×$LÒ$LØ�}‰}‹ÐØ�:‰:�mÓ$€DÜ,6°t¼S×,AÒ,AÀdÇjÁjÇlÂlÔ" 4Ó(Ð\ÐX\Ð\r'   c                ó$   € V ^8„  d   QhR\         /# r‡   r   )r"   s   "r$   r%   r%   5  s   € ÷ 6ñ 6”tñ 6r'   c                  ó$   € \        4       R ,          # )úgateway.pid)rÌ   ri   r'   r$   Ú_get_pid_pathrÿ   5  s   € Ü#Ó%¨Õ5Ð5r'   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# ©r   Úpid_pathr<   ©r   r   )r"   s   "r$   r%   r%   9  s"   € ÷ Kñ K¤X¬d¥^ð K¼tñ Kr'   c                 óP   € T ;'       g    \        4       P                  \        4      # ru   )rÿ   Ú	with_nameÚ_GATEWAY_LOCK_FILENAME©r  s   &r$   Ú_get_gateway_lock_pathr  9  s   € Ø×'Ð'œ›×2Ñ2Ô3IÓJÐJr'   c                ó$   € V ^8„  d   QhR\         /# r‡   r   )r"   s   "r$   r%   r%   =  s   € ÷ =ñ =¤$ñ =r'   c                  ó,   € \        4       \        ,          # ru   )rÌ   Ú_RUNTIME_STATUS_FILEri   r'   r$   Ú_get_runtime_status_pathr  =  s   € Ü#Ó%Ô(<Õ<Ð<r'   c                ó$   € V ^8„  d   QhR\         /# r‡   r   )r"   s   "r$   r%   r%   A  s   € ÷ 2ñ 2”tñ 2r'   c                 ób  € \         P                  ! R4      p V '       d   \        V 4      # \         P                  ! R4      ;'       g    Rp\         P                  P	                  V4      '       d   \        V4      M"\        P
                  ! 4       R,          R,          pVR,          \        ,          # )a!  Cross-profile rendezvous dir for machine-local locks; ``HERMES_GATEWAY_LOCK_DIR`` overrides.

Scope is the **OS user**, not the kernel host: separate users have separate ``$HOME``s,
separate ``~/.hermes`` profile roots and separate credentials, so "one gateway per host"
means "one per host per OS user". Holds the token-scoped locks (:func:`acquire_scoped_lock`)
and the host-role lock + rendezvous record (``gateway/host_rendezvous.py``); the per-home
``gateway.pid``/``gateway.lock`` above deliberately stay under each profile's HERMES_HOME.
ÚHERMES_GATEWAY_LOCK_DIRÚXDG_STATE_HOMEÚ z.localrZ   Úhermes)r¾   Úgetenvr   r:   Úisabsrè   Ú_LOCKS_DIRNAME)ÚoverrideÚstate_home_envÚ
state_homes      r$   Ú_get_lock_dirr  A  sy   € ô �yŠyÐ2Ó3€HßÜ�H‹~Ðô —Y’YÐ/Ó0×6Ð6°B€NÜ)+¯©¯©°~×)FÒ)F”�nÔ%ÌDÏIÊIËKÐZbÕLbÐelÕLl€JØ˜Õ ¤>Õ1Ð1r'   c                ó$   € V ^8„  d   QhR\         /# r‡   ©r!   )r"   s   "r$   r%   r%   T  s   € ÷ )ñ )”cñ )r'   c                  óR   € \         P                  ! \        4      P                  4       # ru   )r   r³   r   Ú	isoformatri   r'   r$   Ú_utc_now_isor  T  s   € Ü�<Š<œÓ×&Ñ&Ó(Ð(r'   g   À¡6ÌAc                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r   Úvaluer<   )r   r   r!   )r"   s   "r$   r%   r%   \  s   € ÷ ñ ¤ð ¬´­ñ r'   c                ó<  € \        V \        4      '       d‘   V P                  4       pVP                  R4      '       d   VRR R,           p \        P
                  ! V4      pTP                  '       d   TP                  4       # TP                  \        R7      P                  4       # \        V \        \        34      '       d«   \        V \        4      '       g•   \        V 4      p\        P                  ! \        4      P                  4       p\         P"                  ! V4      '       d   V\$        8  g   W4R,           8”  d   R#  \        P&                  ! V\        R7      P                  4       # R#   \         d     R# i ; i  \(        \*        \        3 d     R# i ; i)a3  Coerce a persisted ``updated_at`` (ISO string, legacy epoch, hand edit, garbage) to the
RFC3339 ``string | null`` that ``/api/status`` promises. ``str``: iff fromisoformat parses
(trailing ``Z`` tolerated; naive -> UTC). Epoch: before 2000-01-01, > 1 day ahead or
non-finite -> None. ``bool``/other -> None.Nz+00:00)Útzinfoi€Q )Útz)ÚZÚzéÿÿÿÿ)r„   r!   r¸   Úendswithr   Úfromisoformatrº   r"  r¿   r   r  r=   rO   rP   r³   r´   ÚmathÚisfiniteÚ_EPOCH_MIN_PLAUSIBLEÚfromtimestampÚOverflowErrorÚOSError)r   ÚrawÚparsedÚsecondsr³   s   &    r$   Únormalize_updated_atr2  \  s8  € ô
 �%œ×ÒØ�k‰k‹mˆà�<‰<˜
×#Ò#Ø�c�r�(˜XÕ%ˆCð	Ü×+Ò+¨CÓ0ˆFð !Ÿ-Ÿ-˜-�×RÑRÓTÐT¨V¯^©^Ä3¨^Ó-G×RÑRÓTÐTÜ�%œ#œu˜×&Ò&¬z¸%Ä×/FÒ/FÜ˜“,ˆÜ�lŠlœ3Ó×)Ñ)Ó+ˆÜ�}Š}˜W×%Ò%¨Ô3GÔ)GÈ7Ð[`ÕU`ÔK`Ùð	Ü×)Ò)¨'´cÔ:×DÑDÓFÐFñ øô ô 	Úð	ûô œw¬
Ð3ô 	Úð	ús$   ÁE/ Å)F Å/E>Å=E>ÆFÆFÚloop_liveness_watchdogÚshutdown_watchdogc                ó0   € V ^8„  d   QhR\         R\        /# )r   Úruntimer<   )r   r!   )r"   s   "r$   r%   r%   |  s   € ÷ ñ ¤Cð ¬Cñ r'   c                óú   € \        V \        4      '       d   T M/ pVP                  R4      R8w  dK   VP                  R4      R8X  d   R# VP                  R4      R8X  d   VP                  R4      \        9   d   R# R# )al  What a NOT-running gateway's retained ``gateway_state.json`` says about it now:
``"startup_failed"`` (or a watchdog-stamped ``"degraded"``) only while the operator still
wants it running, else ``"stopped"``.

``hermes gateway stop`` keeps the last ``startup_failed`` + ``exit_reason`` on disk for
diagnostics and records the durable stop intent as ``desired_state``; a profile the operator
stopped is "stopped", not a current failure. A watchdog exit (``degraded`` + an exit_reason in
``WATCHDOG_EXIT_REASONS``) is the same kind of current failure as ``startup_failed`` and is kept
under the same rule, so the dashboard agrees with ``hermes gateway status``. Any other retained
state of a dead process (``running``, ``starting``, missing) is just "stopped". Shared by
``/api/status`` and ``/api/messaging/platforms`` so the sidebar strip and the Channels page
cannot disagree.Údesired_stateÚstoppedÚgateway_stateÚstartup_failedÚdegradedÚexit_reason)r„   r    râ   ÚWATCHDOG_EXIT_REASONS)r6  Úrts   & r$   Úretained_gateway_stater@  |  se   € ô ˜w¬×-Ò-‰°2€BØ	‡v�vˆoÓ )Ô+Ø�6‰6�/Ó"Ð&6Ô6Ù#Ø�6‰6�/Ó" jÔ0°R·V±V¸MÓ5JÔNcÔ5cÙÙr'   ÚforceFÚexpected_start_timec                óV   € V ^8„  d   QhR\         R\        R\        \        ,          RR/# )r   ÚpidrA  rB  r<   N)r=   rP   r   rO   )r"   s   "r$   r%   r%   ’  s6   € ÷ 'Cñ 'CÜ	ð'CÜð'CÜ;CÄE½?ð'Cà	ñ'Cr'   c               ó�  € V'       dd   \         '       g   VeT   Vf   \        RV  R24      h\        V 4      pVf   \        RV  R24      h \        W24      '       g   \        RV  R24      h V'       d   \         '       gN   \        P                  ! Y'       g   \        P                  M\        \        R\        P                  4      4       R# ^ RIHp  \        P                  ! R	R
\        V 4      RR.RRRR^
V! 4       RR7      pTP"                  ^ 8w  dQ   TP$                  ;'       g    TP&                  ;'       g    RP)                  4       p\        T;'       g    RT  24      hR#   \        \
        3 d   p\        RT  R24      ThRp?ii ; i  \          d*    \        P                  ! T \        P                  4        R# i ; i)uö  Terminate a PID; POSIX SIGTERM/SIGKILL, Windows taskkill /T /F for force. Identity guard:
Windows ``force`` REQUIRES a matching ``expected_start_time`` (taskkill on a recycled PID has
killed svchost.exe); POSIX optional, but a provided mismatch refuses the kill everywhere.

On POSIX an expectation is optional, but when the caller provides one and it no longer matches the live
process, the kill is refused on every platform â€” a mismatched fingerprint always means the PID was
recycled. See #89614.
Nzrefusing to force-kill PID z# without a process start-time guardz#; process start time is unavailablez; process identity changedz; malformed start timeÚSIGKILL)Úwindows_hide_flagsÚtaskkillz/PIDz/Tz/FTr°   r¿   F)Úcapture_outputÚtextr§   ÚerrorsrN   ÚcreationflagsÚcheckr  ztaskkill failed for PID )Ú_IS_WINDOWSr.  Ú_get_process_start_timeÚ_start_times_agreeÚ	TypeErrorrº   r¾   ÚkillÚsignalÚSIGTERMÚgetattrÚhermes_cli._subprocess_compatrG  Ú
subprocessÚrunr!   ÚFileNotFoundErrorÚ
returncodeÚstderrÚstdoutr¸   )rD  rA  rB  Úcurrent_start_timers   rG  ÚresultÚdetailss   &$$     r$   Úterminate_pidr`  ’  sž  € ÷ —+“+Ð!4Ò!@ØÒ&ÜÐ7¸°uÐ<_Ð`ÓaÐaÜ4°SÓ9ÐØÒ%ÜÐ7¸°uÐ<_Ð`ÓaÐað	^Ü%Ð&8×NÒNÜÐ ;¸C¸5Ð@ZÐ[Ó\Ð\ð O÷ —k“kÜ
�Š�®5”V—^’^´g¼fÀiÔQW×Q_ÑQ_Ó6`ÔaÙå@ðÜ—’Ø˜¤ S£¨4°Ð6ÀtÐRVØ Y¸ÑJ\ÓJ^Øô
ˆð ×Ñ˜AÔØ—=‘=×7Ð7 F§M¡M×7Ð7°R×>Ñ>Ó@ˆÜ�g×AÐAÐ#;¸C¸5Ð!AÓBÐBñ øô# œ:Ð&ô 	^ÜÐ7¸°uÐ<RÐSÓTÐZ]Ð]ûð	^ûô ô Ü
�Š�”V—^‘^Ô$Úðús*   Á E( Ã1F Å(FÅ9F	Æ	FÆ0GÇGc                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   ÚcurrentÚrecordedr<   ©r   rP   )r"   s   "r$   r%   r%   ¼  s&   € ÷ Zñ Z¤ð Z´ð Z¼ñ Zr'   c                óà   a€ \        V 4      oS^ 8„  ;'       dW    \        ;QJ d-    V3R l\        \         V4       4       F  '       d   K   R# 	  R# ! V3R l\        \         V4       4       4      # )zXSame process object: all fingerprints > 0 and within 1ms of ``current``; raises on junk.c              3   óf   <"  € T F&  q^ 8„  ;'       d    \        VS,
          4      R8*  x € K(  	  R# 5i)é    gü©ñÒMbP?N)Úabs)r«   ÚrÚcurs   & €r$   r­   Ú%_start_times_agree.<locals>.<genexpr>¿  s-   øé € ÐYÑDX¸q˜q™5×:Ð:¤S¨¨S­£\°UÑ%:Ô:ÓDXùs   ƒ1“1FT)rO   ÚallÚmap)rb  rc  rj  s   &*@r$   rP  rP  ¼  sO   ø€ ä
�‹.€CØ�‰7×YÐY—s“sÔYÄCÌÈxÔDXÓY—s”sÐY’sÐY�sÔYÄCÌÈxÔDXÓYÓYÐYr'   c                óH   € V ^8„  d   QhR\         R\         R\        R\        /# )r   rc  rb  Ú	tolerancer<   )r   r=   rP   )r"   s   "r$   r%   r%   É  s)   € ÷ :ñ :¬Cð :¼#ð :Ì#ð :Ôosñ :r'   c                óP   € \        \        V4      \        V 4      ,
          4      V8*  # )a  Liveness-reconciliation comparator for :func:`get_process_start_time` fingerprints: the
recorded owner and the current reading are the same incarnation when they agree within
``tolerance``. Raises on junk; callers decide what an unreadable (``None``) side means.)rh  r=   )rc  rb  ro  s   &&&r$   Ústart_time_fingerprints_matchrq  É  s!   € ô Œs�7‹|œc (›mÕ+Ó,°	Ñ9Ð9r'   c                ó0   € V ^8„  d   QhR\         R\         /# )r   Úidentityr<   r  )r"   s   "r$   r%   r%   Ð  s   € ÷ Eñ Eœ#ð E¤#ñ Er'   c                 óv   € \         P                  ! V P                  R 4      4      P                  4       R,          # )r°   :Né   N)ÚhashlibÚsha256ÚencodeÚ	hexdigest)rs  s   &r$   Ú_scope_hashrz  Ð  s(   € Ü�>Š>˜(Ÿ/™/¨'Ó2Ó3×=Ñ=Ó?ÀÕDÐDr'   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   Úscopers  r<   )r!   r   )r"   s   "r$   r%   r%   Ô  s&   € ÷ Eñ E¤ð E¬sð E´tñ Er'   c                 óB   € \        4       V  R \        V4       R2,          # )Ú-z.lock)r  rz  )r|  rs  s   &&r$   Ú_get_scope_lock_pathr  Ô  s"   € Ü‹? ˜w a¬°HÓ(=Ð'>¸eÐDÕDÐDr'   c                óF   € V ^8„  d   QhR\         R\        \         ,          /# ©r   rD  r<   ©r=   r   )r"   s   "r$   r%   r%   Ø  s   € ÷  ñ  ¤ð  ¬´#­ñ  r'   c                óV  € \        RV  R24      p \        VP                  RR7      P                  4       ^,          4      #   \        \
        \        \        \        3 d     Mi ; i ^ RI	p^ RI
Hp \        T! TP                  T 4      4      ^d,          4      #   \         d     R# i ; i)u‘  Return a stable per-process start-time fingerprint, or None.

Used as a PID-reuse guard: a ``(pid, start_time)`` pair uniquely identifies
a process, so a recycled PID (same number, different process) yields a
different value and is never mistaken for the original.

On Linux this is field 22 of ``/proc/<pid>/stat`` (start time in clock
ticks since boot, an int).  On platforms without ``/proc`` (macOS, Windows)
we fall back to ``psutil.Process(pid).create_time()`` â€” a float epoch
timestamp â€” quantized to an int (centiseconds) for stable equality.

The two sources are never mixed on a single platform: ``/proc`` always
succeeds first on Linux, and always fails on macOS/Windows so psutil is
always used there.  Because the guard only compares the value recorded at
spawn against the live value *on the same host*, the differing units across
platforms are irrelevant â€” only same-source equality matters.
ú/proc/z/statr°   r¦   N)Úprocess_birth)r   r=   r¶   ÚsplitrY  Ú
IndexErrorÚPermissionErrorrº   r.  ÚpsutilÚhermes_cli.process_identityr…  ÚroundÚProcessrÂ   )rD  Ú	stat_pathr‰  r…  s   &   r$   rO  rO  Ø  s›   € ô$ �v˜c˜U %Ð(Ó)€Iðä�9×&Ñ&°Ð&Ó8×>Ñ>Ó@ÀÕDÓEÐEøÜœz¬?¼JÌÐPô Ùðúð
ÛÝ=Ü‘] 6§>¡>°#Ó#6Ó7¸#Õ=Ó>Ð>øÜô Úðús#   ‘/A Á A$Á#A$Á(0B ÂB(Â'B(c                óF   € V ^8„  d   QhR\         R\        \         ,          /# r�  r‚  )r"   s   "r$   r%   r%   û  s   € ÷ (ñ (¤ð (¬´­ñ (r'   c                ó   € \        V 4      # )zBPublic wrapper for retrieving a process start time when available.)rO  ©rD  s   &r$   Úget_process_start_timer‘  û  s   € ä" 3Ó'Ð'r'   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# r�  )r=   r   r!   )r"   s   "r$   r%   r%      s   € ÷ ñ œsð ¤x´¥}ñ r'   c                ó  € \         P                  ! \        4      ;_uu_ 4        \        RV  R24      P	                  4       pV'       d<   VP                  RR4      P                  RRR7      P                  4       uuRRR4       #  RRR4       \         P                  ! \        4      ;_uu_ 4        ^ RI	pVP                  V 4      P                  4       pV'       d   R	P                  V4      uuRRR4       #  RRR4       \        '       g½   \         P                  ! \        \        P                  4      ;_uu_ 4        \        P                   ! R
R\#        V 4      RR.RRRR^RR7      pVP$                  ^ 8X  dE   VP&                  P                  4       '       d%   VP&                  P                  4       uuRRR4       # RRR4       R# R#   + '       g   i     ELM; i  + '       g   i     Lî; i  + '       g   i     R# ; i)uò  Process command line as one string: /proc, then psutil, then ``ps``.

Order is by cost, and this runs per live gateway on every roster/status poll. ``psutil`` reads
the process table in-process (a ``sysctl`` on macOS) where ``ps`` costs a fork+exec â€” measured
0.02ms against 4.2ms on macOS for the same string. It cannot always answer: on macOS it raises
``AccessDenied`` for a process owned by another user, which ``ps`` still reports, so ``ps``
stays as the fallback rather than being replaced.r„  z/cmdlineó    ó    r°   Úignore)rK  NÚ Úpsú-pz-ozcommand=Tr¿   F)rI  rJ  r§   rK  rN   rM  )rð   rñ   r.  r   Ú
read_bytesr¿   Údecoder¸   rÂ   r‰  rŒ  Úcmdliner½   rN  rW  ÚTimeoutExpiredrX  r!   rZ  r\  )rD  r/  r‰  Úcmdline_partsr^  s   &    r$   Ú_read_process_cmdlinerŸ     so  € ô 
×	Ò	œW×	%Õ	%Ü�V˜C˜5 Ð)Ó*×5Ñ5Ó7ˆßØ—;‘;˜w¨Ó-×4Ñ4°WÀXÐ4ÓN×TÑTÓV÷ 
&Ò	%à÷ 
&ô 
×	Ò	œY×	'Õ	'ÛØŸ™ sÓ+×3Ñ3Ó5ˆßØ—8‘8˜MÓ*÷	 
(Ò	'ð ÷ 
(÷
 ‹;Ü× Ò ¤¬*×*CÑ*C×DÕDÜ—^’^Ø�tœS ›X t¨ZÐ8Ø#¨$¸ÈÐ\]ØôˆFð
 × Ñ  AÔ%¨&¯-©-×*=Ñ*=×*?Ò*?Ø—}‘}×*Ñ*Ó,÷ E×DÒDó ÷% 
&×	%Ð	%ú÷ 
(×	'ú÷ EÖDñ ús+   £AG	Â/<GÄ<AG0ÆG0Ç	G	ÇG-	Ç0H	c                óL   € V ^8„  d   QhR\         R,          R\         R,          /# ©r   ÚcommandNr<   r  )r"   s   "r$   r%   r%     s&   € ÷ Dñ D¬¨t­ð D¼¸d½
ñ Dr'   c                óâ  a
€ V '       g   R#  \         P                  ! V RR7      pV Uu. uF#  q"P                  R4      P	                  RR4      NK%  	  ppV Uu. uF  q"P                  4       NK  	  upo
S
'       g   R# S
 Uu. uF  q"P                  R^4      R,          NK  	  pp\        V4      '       dX   \        V4      pVf   R# V Uu. uF  q"P                  4       NK  	  upo
S
 Uu. uF  q"P                  R^4      R,          NK  	  ppV^ ,          R8X  d   R# \        ;QJ d    R S
 4       F  '       g   K   R	M	  RM! R S
 4       4      '       d   R
# \        ;QJ d8    V
3R l\        \        S
4      ^,
          4       4       F  '       g   K   R	M-	  RM)! V
3R l\        \        S
4      ^,
          4       4       4      '       d   R
# \        ;QJ d    R V 4       F  '       g   K   R	M	  RM! R V 4       4      '       d   R
# \        ;QJ d    R V 4       F  '       g   K   R	M	  RM! R V 4       4      '       d   R
# RP                  S
4      pRV9  dD   RV9  d=   \        ;QJ d    R V 4       F  '       g   K   R	M	  RM! R V 4       4      '       g   R# . pRpS
 FD  pV'       d   RpK  VR9   d   R	pK  VP                  R4      '       d   K3  VP                  V4       KF  	  \        V4       F8  w  r˜VR8X  g   K  V	^,           \        V4      8  d   Wi^,           ,          u # R
u # 	  R#   \         d    T P                  4       p EL/i ; iu upi u upi u upi u upi u upi )aÂ  Hermes gateway lifecycle subcommand from a command line, or None. No loose substring matches
(``"gateway" in cmdline`` also matched ``gateway status`` / ``python -m tui_gateway``): needs a
Hermes entrypoint plus the ``gateway`` subcommand, or a gateway-dedicated entrypoint. Tokenizes
quote-aware (Windows paths with spaces); ``--profile``/``-p`` selectors are stripped anywhere in
argv since ``_apply_profile_override`` removes them before argparse.NF©Úposixú"'Ú\Ú/Ú	osascriptc              3   ó\   "  € T F"  qR 8H  ;'       g    VP                  R4      x € K$  	  R# 5i)zgateway/run.pyz/gateway/run.pyN)r'  )r«   Úts   & r$   r­   Ú._gateway_command_subcommand.<locals>.<genexpr>B  s)   é € Ð
RÉ6ÀaÐ Ñ ×AÐA A§J¡JÐ/@Ó$AÔAË6ùs   ‚,’,TrX  c              3   ór   <"  € T F,  pSV,          R 8H  ;'       d    SV^,           ,          R8H  x € K.  	  R# 5i)z-mzgateway.runNri   )r«   ÚiÚtokenss   & €r$   r­   r¬  D  s4   øé € Ð
`ÑI_ÀAˆ6�!�9˜Ñ×?Ð? ¨¨A­¥°-Ñ!?Ô?ÓI_ùs   ƒ7›7c              3   ó*   "  € T F	  qR 8H  x € K  	  R# 5i)zdesktop-gateway.pyNri   ©r«   Úbs   & r$   r­   r¬  J  s   é € Ð
8©i¨Ð$Ö$«iùó   ‚c              3   ó*   "  € T F	  qR9   x € K  	  R# 5i)r   N)r   zhermes-gateway.exeri   r±  s   & r$   r­   r¬  L  s   é € Ð
LÁ)¸QÐ8Ö8Ã)ùr³  r—  úhermes_cli.mainzhermes_cli/main.pyc              3   ó*   "  € T F	  qR9   x € K  	  R# 5i)r  N)r  z
hermes.exeri   r±  s   & r$   r­   r¬  O  s   é € ð ZÙ/8¨!Ð%Ö%«yùr³  Úgatewayr&  )ú	--profiler™  )ú
--profile=z-p=)Úshlexr†  rº   r¸   r¿   ÚlowerÚrsplitr   r   ÚanyÚrangerÀ   r½   Ú
startswithr¹   Ú	enumerate)r¢  Ú
raw_tokensr«  Úcased_tokensÚ	basenamesÚjoinedÚfilteredÚ	skip_nextÚtokenr®  r¯  s   &         @r$   Ú_gateway_command_subcommandrÈ    sÆ  ø€ ÷ Ùð%Ü—[’[ °Ô6ˆ
ñ @JÓJ¹z¸!—G‘G˜E“N×*Ñ*¨4°Ö5¹z€LÐJÙ!-Ó.¡˜A�g‰gŽi¡Ñ.€FßÙÙ/5Ó6©v¨!—‘˜#˜qÓ! "×%Ð%©v€IÐ6ô ' |×4Ò4ô -¨\Ó:ˆØÒÙÙ%1Ó2¡\ —'‘'–)¡\Ñ2ˆÙ39Ó:±6¨a—X‘X˜c 1Ó% b×)Ð)±6ˆ	Ð:ð �…|�{Ô"Ù÷
 ƒsÑ
RÉ6Ó
R‡s‡s‚sÑ
RÉ6Ó
R×RÒRÙß
ƒsÔ
`ÌÌsÐSYË{Ð]^ÍÔI_Ó
`‡s‡s‚sÔ
`ÌÌsÐSYË{Ð]^ÍÔI_Ó
`×`Ò`Ù÷
 ƒsÑ
8©iÓ
8‡s‡s‚sÑ
8©iÓ
8×8Ò8Ùß
ƒsÑ
LÁ)Ó
L‡s‡s‚sÑ
LÁ)Ó
L×LÒLÙØ�X‰X�fÓ€FØ Ô&Ð+?ÀvÔ+M×VYÓVYñ ZÙ/8óZ×VY×VYÒVYñ ZÙ/8óZ÷ Wò Wñ à€HØ€IÛˆßØŠIØÐ)Ô)ØŠIØ×!Ñ!Ð"7×8Ô8Ø�O‰O˜EÖ"ñ ô ˜hÖ'‰ˆØ�IÖà&'¨!¥e¬c°(«mÔ&;�8 �E•?ÒFÀÒFñ (ñ øôu ô %Ø—]‘]“_‹
ð%üò KùÚ.ùò 7ùò 3ùÚ:s.   �L6 ©)MÁMÂ!M"Ã
M'Ã)!M,Ì6MÍMc                óL   € V ^8„  d   QhR\         R,          R\         R,          /# r¡  r  )r"   s   "r$   r%   r%   d  s"   € ÷ ñ ¬S°4­Zð ¼CÀ$½Jñ r'   c                óÈ  € \        V 4      pVf	   V '       g   V#  \        P                  ! V RR7      pV Uu. uF#  q3P	                  R4      P                  RR4      NK%  	  pp\        V4      pVf   R# V^,           p\        V\        V4      4       F'  p\        RP                  W'R 4      4      pVf   K%  Vu # 	  R#   \         d    T P                  4       p L¨i ; iu upi )uë  Gateway lifecycle subcommand a command line would EVENTUALLY launch, or None.

The identity matcher (``_gateway_command_subcommand``) deliberately refuses ``python -c <src>
â€¦``: the trailing argv is the inline program's data, not that process's own identity (#107002).
Callers that inspect a command line as SPAWN INTENT â€” "if I launch this, does a gateway runtime
eventually appear?" â€” need the opposite answer, because
``gateway._spawn_gateway_restart_watcher`` hides a real ``â€¦ -m hermes_cli.main gateway run``
behind exactly that wrapper. ``tests/_fixtures/live_system_guard.py`` is the canonical caller.

Still no substring matching: the wrapper is peeled token-wise and each remaining suffix is
handed to the same canonical matcher.
NFr¤  r¦  r§  r¨  r—  )
rÈ  rº  r†  rº   r¸   r¿   r   r¾  rÀ   r½   )	r¢  ÚdirectrÁ  r«  rÂ  Ú
flag_indexrH   r®  Únesteds	   &        r$   Úgateway_spawn_intent_subcommandrÎ  d  sÔ   € ô )¨Ó1€FØÒ§Øˆð%Ü—[’[ °Ô6ˆ
ñ @JÓJ¹z¸!—G‘G˜E“N×*Ñ*¨4°Ö5¹z€LÐJÜ)¨,Ó7€JØÒÙð ˜�N€EÜ�5œ#˜lÓ+Ö,ˆÜ,¨S¯X©X°jÀ°nÓ-EÓFˆØÔØŠMñ -ñ øô ô %Ø—]‘]“_Š
ð%üâJs   ›B> ·)CÂ>CÃCc                ó>   € V ^8„  d   QhR\         R,          R\        /# r¡  ©r!   rP   )r"   s   "r$   r%   r%   †  s   € ÷ 9ñ 9¬S°4­Zð 9¼Dñ 9r'   c                ó   € \        V 4      R8H  # )z:True only for a real ``gateway run`` process command line.rX  ©rÈ  ©r¢  s   &r$   Úlooks_like_gateway_command_linerÔ  †  s   € ä& wÓ/°5Ñ8Ð8r'   c                ó>   € V ^8„  d   QhR\         R,          R\        /# r¡  rÐ  )r"   s   "r$   r%   r%   ‹  s"   € ÷ Fñ F´S¸4µZð FÄDñ Fr'   c                ó   € \        V 4      R9   # )a  True for command lines that can host the runtime (``run`` or ``restart``: without a service
manager the manual restart fallback runs ``run_gateway()`` in-process). For validating
Hermes-owned records / cleanup scans only; ``looks_like_gateway_command_line`` stays strict.>   rX  ÚrestartrÒ  rÓ  s   &r$   Ú'looks_like_gateway_runtime_command_linerØ  ‹  s   € ô ' wÓ/Ð3EÑEÐEr'   c                ó0   € V ^8„  d   QhR\         R\        /# r�  ©r=   rP   )r"   s   "r$   r%   r%   ’  s   € ÷ Fñ F¤Sð F¬Tñ Fr'   c                óT   € \        V 4      p\        V4      ;'       d    \        V4      # )z;True when the live PID still looks like the Hermes gateway.)rŸ  rP   rÔ  )rD  rœ  s   & r$   Ú_looks_like_gateway_processrÜ  ’  s$   € ä# CÓ(€GÜ�‹=×EÐEÔ<¸WÓEÐEr'   c                óR   € V ^8„  d   QhR\         \        \        3,          R\        /# r÷   )r    r!   r   rP   )r"   s   "r$   r%   r%   ˜  s&   € ÷ Yñ Y¤t¬C´¨H¥~ð Y¼$ñ Yr'   c                óÚ   € V P                  R4      pV P                  R4      \        8w  g   \        V\        4      '       d	   V'       g   R# \	        RP                  R V 4       4      4      # )zMValidate gateway identity from PID-file metadata when cmdline is unavailable.ÚargvÚkindFr—  c              3   ó8   "  € T F  p\        V4      x € K  	  R # 5iru   r  )r«   Úparts   & r$   r­   Ú-_record_looks_like_gateway.<locals>.<genexpr>�  s   é € Ð;WÑRVÈ$¼CÀ¿I¸IÓRVùr¯   )râ   Ú_GATEWAY_KINDr„   ÚlistrØ  r½   )rß   rß  s   & r$   Ú_record_looks_like_gatewayræ  ˜  sN   € à�:‰:�fÓ€DØ‡z�z�&Óœ]Ô*´*¸TÄ4×2HÒ2H×PTÙÜ2°3·8±8Ñ;WÑRVÓ;WÓ3WÓXÐXr'   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# ©r   Úprofile_homer<   ©r   r   r!   )r"   s   "r$   r%   r%      s"   € ÷ Qñ Q¬ð Q´(¼3µ-ñ Qr'   c                óT   € V P                   P                  R8X  d   V P                  # R# )zYProfile id for ``<root>/profiles/<name>``; None for the root/default home (bare gateway).rê   N)r²   rB   )ré  s   &r$   Ú_profile_name_for_homerì     s&   € à ,× 3Ñ 3× 8Ñ 8¸JÔ Fˆ<×ÑÐPÈDÐPr'   c                óF   € V ^8„  d   QhR\         R\        \         ,          /# ©r   r¢  r<   )r!   r   )r"   s   "r$   r%   r%   ¥  s   € ÷ 	ñ 	¤ð 	¬´­ñ 	r'   c                ó–  € \        V P                  4       4      ;'       g    V P                  4        Uu. uF  qP                  4       NK  	  pp\        V4       Fg  w  r4VP	                  R4      '       d   VP                  R4      ^,          u # VR9   g   K?  V^,           \        V4      8  g   KX  W#^,           ,          u # 	  R# u upi )zÄLowercased ``-p``/``--profile`` argument of a case-preserved command line (a bootstrap's interpreter
``-P`` is no ``-p``, #127865), or None. Token equality: ``-p ops`` must not claim ``-p ops-2``.r¹  Ú=N)r™  r¸  )r   r†  r»  rÀ  r¿  Ú	partitionrÀ   )r¢  r«  r¯  r®  Útoks   &    r$   Úprofile_flag_valueró  ¥  s�   € ô "7°w·}±}³Ó!G×!ZÐ!ZÈ7Ï=É=Ë?Ð!ZÓ[Ñ!Z˜A�g‰gŽiÑ!Z€FÐ[Ü˜FÖ#‰ˆØ�>‰>˜,×'Ò'Ø—=‘= Ó% aÕ(Ò(ØÐ%Ö%¨!¨a­%´#°f³+Ö*=Ø˜a�%•=Ò ñ	 $ñ
 ùò \s   ´Cz4(?:^|\s)hermes_home=(?:\"([^\"]*)\"|'([^']*)'|(\S+))c                óF   € V ^8„  d   QhR\         R\        \         ,          /# rî  )r!   rå  )r"   s   "r$   r%   r%   ´  s   € ÷ ñ ¤Sð ¬T´#­Yñ r'   c                ó°   € \         P                  V 4       Uu. uF2  p\        R VP                  4        4       4      P	                  R4      NK4  	  up# u upi )a<  Values of every ``HERMES_HOME=<value>`` assignment in ``command`` (the caller lowercases
and normalizes separators). Values are token-bounded, quotes stripped: the substring test
this replaces let ``HERMES_HOME=/root/profiles/ops`` claim a ``/root/profiles/ops2`` gateway.
The name is token-bounded too (``FOO=hermes_home=/x`` is not an assignment), and a trailing
separator on the value is stripped -- ``HERMES_HOME=/root/.hermes/`` (systemd ``Environment=``
or a shell wrapper spelling) is the same home as ``/root/.hermes``; callers strip the profile
home the same way.c              3   ó0   "  € T F  qf   K  Vx € K  	  R # 5iru   ri   )r«   Úgs   & r$   r­   Ú*hermes_home_assignments.<locals>.<genexpr>½  s   é € Ð4™
�1�QŠQ›
ùs   ‚Œ
r¨  )Ú_HERMES_HOME_ASSIGNMENT_REÚfinditerÚnextÚgroupsÚrstrip)r¢  Úms   & r$   Úhermes_home_assignmentsrÿ  ´  sP   € ô ,×4Ñ4°WÔ=óá=ˆAô 	Ñ4˜Ÿ™œ
Ó4Ó4×;Ñ;¸CÖ@Ù=ñð ùò s   ˜8Ac                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   Ú
command_lcÚhome_lcr<   rÐ  )r"   s   "r$   r%   r%   Â  s&   € ÷ eñ e¬sð e¼Sð eÄTñ er'   c                óˆ   € V\        V 4      9   d   R# \        P                  ! R\        P                  ! V4       R2V 4      RJ# )aX  True when ``command_lc`` carries ``HERMES_HOME=<home_lc>`` (both lowercased, ``/``-separated,
no trailing separator). Argv reaches us space-joined, so an unquoted value with a space in it
(``HERMES_HOME=C:/Users/John Doe/.hermes``) is cut at the space by the token parser; a
token-bounded literal match of the whole home recovers that spelling.Tz(?:^|\s)hermes_home=z
/?(?=\s|$)N)rÿ  ÚreÚsearchÚescape)r  r  s   &&r$   Úcommand_line_names_hermes_homer  Â  s@   € ð
 Ô)¨*Ó5Ô5ÙÜ�9Š9Ð,¬R¯YªY°wÓ-?Ð,@À
ÐKÈZÓXÐ`dÐdÐdr'   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   r¢  ré  r<   )r!   r   rP   )r"   s   "r$   r%   r%   Ì  s&   € ÷ jñ j¬cð jÄð jÌ$ñ jr'   c                óž  € V P                  4       P                  RR4      p\        V4      p\        V4      P                  4       P                  RR4      P	                  R4      pVe3   VR8w  d,   \        V 4      VP                  4       8X  d   R# \        W$4      # \        V 4      R9  d   R# \        V4      '       * ;'       g    \        W$4      # )aM  True when a gateway command line belongs to ``profile_home`` (mirrors
``hermes_cli.gateway._matches_current_profile``): a stale state file can record a PID recycled
onto ANOTHER profile's live gateway. Named profiles carry ``-p``/``--profile <name>`` or
``HERMES_HOME=`` on argv; the default gateway runs bare. Separators normalized.r§  r¨  rë   TF)Nrë   )r»  r¿   rì  r!   rý  ró  r  rÿ  )r¢  ré  r  Úprofile_namer  s   &&   r$   Ú _command_line_belongs_to_profiler  Ì  s²   € ð
 —‘“×(Ñ(¨¨sÓ3€JÜ)¨,Ó7€LÜ�,Ó×%Ñ%Ó'×/Ñ/°°cÓ:×AÑAÀ#ÓF€GØÒ L°IÔ$=Ü˜gÓ&¨,×*<Ñ*<Ó*>Ô>ÙÜ-¨jÓBÐBô ˜'Ó"Ð*;Ô;ÙÜ& zÓ2Ô2×iÐiÔ6TÐU_Ó6iÐir'   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   rD  ré  r<   )r=   r   rP   )r"   s   "r$   r%   r%   ã  s&   € ÷ hñ h¤3ð h´dð h¼tñ hr'   c                óº   €  ^ RI HpHp V! 4       pTRJ;'       d/    TP                  T 8H  ;'       d    TP                  T! T4      4      #   \         d     R# i ; i)uÅ  Does the ONE host gateway â€” PID ``pid`` â€” serve ``profile_home``'s profile?

Argv cannot answer this: the host singleton runs ONE home's (usually bare/default) command line
while multiplexing every profile, so :func:`_command_line_belongs_to_profile` rejects every
secondary and the profile reads as "not running" while its messages are being served. The live
served set is the only proof; the argv rule stays as the fallback when no record exists.
)Úhost_gatewayÚprofile_name_for_homeFN)Úgateway.host_attachr  r  rÂ   rD  Úserves)rD  ré  r  r  Úowners   &&   r$   Ú_host_gateway_serves_homer  ã  s[   € ðßKá“ˆð ˜Ð×gÐg §¡¨cÑ!1×gÐg°e·l±lÑCXÐYeÓCfÓ6gÐgøô ô Úðús   ‚A ÁAÁAc                ó€   € V ^8„  d   QhR\         \        \        3,          R\        R\        \
        ,          R\        /# )r   rß   rD  rÝ   r<   )r    r!   r   r=   r   r   rP   )r"   s   "r$   r%   r%   ô  s>   € ÷ bñ bÜ””c��NðbÜ!$ðbÜ8@Ä½ðbä	ñbr'   c               óÀ   € \        V4      pV'       g   \        V 4      # \        V4      '       g   R# Ve   \        W4      '       d   R# VRJ ;'       g    \	        W24      # )u>  True when a live PID still identifies as this gateway record. The live command line wins (a
stale record's argv must not make a recycled PID count as a gateway; with ``expected_home`` it
must also belong to that profile â€” or serve it as the host multiplexer); unreadable cmdline
(Windows/EACCES) -> persisted record.FNT)rŸ  ræ  rØ  r  r  )rß   rD  rÝ   Úlive_cmdlines   &&$ r$   Ú _record_matches_live_gateway_pidr  ô  sW   € ô )¨Ó-€LßÜ)¨&Ó1Ð1Ü2°<×@Ò@ÙØÒ Ô%>¸s×%RÒ%RÙØ˜DÐ ×aÐaÔ$DÀ\Ó$aÐar'   c                ó:   € V ^8„  d   QhR\         \        ,          /# r‡   )rå  r!   )r"   s   "r$   r%   r%     s   € ÷ ñ ”dœ3•iñ r'   c                 óØ   € \        \        P                  4      p \        P                  P	                  R4      pV R,          R.8X  d#   \        VRR4      '       d   VP                  V ^ &   V # )u{  ``sys.argv`` with the inline-source placeholder replaced by the entry point this process runs.

The published launcher script (``_launchers._launcher_script``: the POSIX ``bin/hermes`` shell
launcher and the Windows ``.cmd``) imports ``hermes_cli.main`` inside ``python -I -c <script>``,
so ``sys.argv`` is ``["-c", "gateway", "run"]`` â€” a record the argv matcher can never accept
once the live command line is unreadable (Windows/EACCES fallback in
``_record_matches_live_gateway_pid``). Recording the module path follows runpy's ``alter_sys``
convention, which is what the ``--run-module`` and store-launcher forms already persist.rµ  :Nr?   Nz-cÚ__file__N)rå  Úsysrß  Úmodulesrâ   rU  r  )rß  Úentrys     r$   Ú_record_argvr    sR   € ô ”—‘‹>€DÜ�K‰K�O‰OÐ-Ó.€EØˆB…x�D�6Ôœg e¨Z¸×>Ò>Ø—.‘.ˆˆQ‰Ø€Kr'   c                ó$   € V ^8„  d   QhR\         /# r‡   )r    )r"   s   "r$   r%   r%     s   € ÷ ñ œ4ñ r'   c                  óÄ   € R \         P                  ! 4       R\        R\        4       R\	        \         P                  ! 4       4      R\        \        \        4       4      4      /# )rD  rà  rß  Ú
start_timerá   )r¾   Úgetpidrä  r  rO  r!   rÔ   rÌ   ri   r'   r$   Ú_build_pid_recordr#    sH   € àŒr�yŠy‹{˜F¤M°6¼<»>ØÔ-¬b¯iªi«kÓ:ð 	”sÔ1Ô2JÓ2LÓMÓNðð r'   c                óF   € V ^8„  d   QhR\         \        \        3,          /# r‡   ©r    r!   r   )r"   s   "r$   r%   r%     s   € ÷ ñ ¤4¬¬S¨¥>ñ r'   c                 óŒ   €  ^ RI Hp  V ! 4       pRVP                  R4      RVP                  R4      /#   \         d    / u # i ; i)u  Code identity of THIS process for ``gateway_state.json`` (restart picked up new code?).
Lazy import keeps ``gateway.status`` free of ``hermes_cli`` at import time. Never raises.

A gateway keeps serving the module versions it imported at startup, so stamping the identity into
``gateway_state.json`` lets `hermes update` (and the dashboard) prove whether a running gateway actually
picked up new code after the restart phase â€” instead of assuming it did (#88654, #69754). Never raises;
degrades to absent fields.
)Úget_code_identityÚcode_shaÚshaÚcode_versionÚversion)Úhermes_cli.version_infor'  râ   rÂ   )r'  rs  s     r$   Ú_get_code_identity_fieldsr-    sG   € ðÝ=á$Ó&ˆØ˜HŸL™L¨Ó/°ÀÇÁÈiÓAXÐYÐYøÜô ØŠ	ðús   ‚03 ³AÁAc                óh   € V ^8„  d   QhR\         \        \        \        3,          ,          R\        /# r÷   ©r   r    r!   r   rP   )r"   s   "r$   r%   r%   1  s,   € ÷ Yñ Y´8¼DÄÄcÀ½NÕ3Kð YÔPTñ Yr'   c                óš   € \        V \        4      '       g   R# V P                  R4      pV'       * ;'       g    \        V\	        4       4      # )z´True when the record's ``hermes_home`` matches the current process (legacy records: True);
another HERMES_HOME's record must be ignored or the default gateway assumes its identity.Frá   )r„   r    râ   rÜ   rÌ   )rß   Úrecord_homes   & r$   Ú&_pid_record_belongs_to_current_profiler2  1  s>   € ô �fœd×#Ò#ÙØ—*‘*˜]Ó+€KØŒ?×XÐXÔ/°Ô=UÓ=WÓXÐXr'   c                óF   € V ^8„  d   QhR\         \        \        3,          /# r‡   r%  )r"   s   "r$   r%   r%   :  s   € ÷ ñ ¤d¬3´¨8¥nñ r'   c                  ób   € / \        4       CR RRRRRR^ R/ RR	R
/R\        4       /C\        4       C# )r:  Ústartingr=  NÚrestart_requestedFÚactive_agentsÚ	platformsÚsession_storeÚstatusÚunknownÚ
updated_at)r#  r  r-  ri   r'   r$   Ú_build_runtime_status_recordr=  :  sO   € ðÜ
Ó
ðØ.°
¸MÈ4Ø˜U O°Q¸ÀRØ˜( IÐ.°¼l»nñô $Ó
%ð	ð r'   Úbare_pid_okc          	      ót   € V ^8„  d   QhR\         R\        R\        \        \        \
        3,          ,          /# )r   r:   r>  r<   )r   rP   r   r    r!   r   )r"   s   "r$   r%   r%   C  s/   € ÷ :ñ :œ$ð :´ð :ÄÌ$ÌsÔTWÈxÍ.ÕAYñ :r'   c               ó  €  V P                  RR7      P                  4       pT'       g   R#  \        P
                  ! T4      pT'       d   \        T\        4      '       d   RT/# \        T\        4      '       d   T# R#   \        \        3 d     R# i ; i  \        P                   d[    RpT'       dN   \        P                  ! \        4      ;_uu_ 4        \        T4      pRRR4        K¬    + '       g   i      L½; i LÂi ; i)z”JSON object at ``path``, or None when absent/empty/unreadable/invalid. ``bare_pid_ok`` also
accepts legacy bare-integer PID files as ``{"pid": N}``.r¥   r¦   NrD  )r¶   r¸   r.  ÚUnicodeDecodeErrorÚjsonÚloadsÚJSONDecodeErrorrð   rñ   rº   r=   r„   r    )r:   r>  r/  r;   s   &$  r$   rƒ   rƒ   C  sÕ   € ðØ�n‰n kˆnÓ2×8Ñ8Ó:ˆ÷ Ùð#Ü—*’*˜S“/ˆ÷ ”z '¬3×/Ò/Ø�wÐÐÜ  ¬$×/Ò/ˆ7Ð9°TÐ9øô! Ô'Ð(ô ò ð	ûô ×Ñô #ØˆßÜ×$Ò$¤Z×0Õ0Ü˜c›(�÷ 1×0×0Ó0úñ ð#úsF   ‚ A? ­B Á?BÂBÂDÂ6"DÃC/Ã$DÃ/D Ã:DÄ DÄDc                óV   € V ^8„  d   QhR\         R\        \        \        3,          RR/# )r   r:   r;   r<   Nr�   )r"   s   "r$   r%   r%   [  s.   € ÷ Iñ Iœ4ð I¬$¬s´C¨x­.ð I¸Tñ Ir'   c                 ó"   € \        WR RR7       R # )N)ÚindentÚ
separators)Ú,Ú:r   )r:   r;   s   &&r$   rk   rk   [  s   € Ü�d¨D¸Z×Hr'   c                ó(   € V ^8„  d   QhR\         RR/# )r   r:   r<   Nr   )r"   s   "r$   r%   r%   _  s   € ÷ %ñ %œ$ð % 4ñ %r'   c                 ó¨   € \         P                  ! \        4      ;_uu_ 4        V P                  R R7       RRR4       R#   + '       g   i     R# ; i)T©Ú
missing_okN)rð   rñ   r.  ÚunlinkrÓ   s   &r$   Ú_unlink_quietlyrP  _  s0   € Ü	×	Ò	œW×	%Õ	%Ø�‰˜tˆÔ$÷ 
&×	%×	%Ò	%ús   £A Á A	c                ó\   € V ^8„  d   QhR\         \        ,          R\         \        ,          /# r  )r   r   r    )r"   s   "r$   r%   r%   d  s&   € ÷ Jñ Jœx¬�~ð J¼Ä$½ñ Jr'   c                 ó@   € \        T ;'       g    \        4       R R7      # ©T)r>  )rƒ   rÿ   r  s   &r$   Ú_read_pid_recordrT  d  s   € Ü˜8×6Ð6¤}£ÀDÔIÐIr'   c                ó~   € V ^8„  d   QhR\         \        ,          R\         \        \        \        3,          ,          /# ©r   Ú	lock_pathr<   ©r   r   r    r!   r   )r"   s   "r$   r%   r%   h  s2   € ÷ Tñ T¬´$­ð TÄ8ÌDÔQTÔVYÐQYÍNÕC[ñ Tr'   c                 ó@   € \        T ;'       g    \        4       R R7      # rS  )rƒ   r  )rW  s   &r$   Ú_read_gateway_lock_recordrZ  h  s   € Ü˜9×@Ð@Ô(>Ó(@ÈdÔSÐSr'   c                óŠ   € V ^8„  d   QhR\         \        \        \        3,          ,          R\        R\         \        ,          /# )r   rß   Úkeyr<   ©r   r    r!   r   r=   )r"   s   "r$   r%   r%   l  s3   € ÷ ñ œX¤d¬3´¨8¥nÕ5ð ¼Cð ÌHÔUXÍMñ r'   c                 ó`   €  \        W,          4      #   \        \        \        3 d     R # i ; iru   )r=   ÚKeyErrorrQ  rº   )rß   r\  s   &&r$   Ú_pid_from_recordr`  l  s-   € ðÜ�6•;ÓÐøÜ”i¤Ð,ô Úðús   ‚ “-¬-c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   Úrecorded_startÚcurrent_startr<   rd  )r"   s   "r$   r%   r%   s  s&   € ÷ [ñ [¬#ð [¼cð [Ädñ [r'   c                ó&   € RW39  ;'       d    W8g  # )zFPID-reuse guard: True only when BOTH start times are known and differ.Nri   )rb  rc  s   &&r$   Ú_start_times_conflictre  s  s   € à˜Ð6Ñ6×ZÐZ¸=Ñ;ZÐZr'   c                ó~   € V ^8„  d   QhR\         \        \        \        3,          ,          R\         \        ,          /# r÷   r]  )r"   s   "r$   r%   r%   x  s+   € ÷ ñ ¤(¬4´´S°­>Õ":ð ¼xÌ½}ñ r'   c                ó¢   € \        V 4      pVe   \        V4      '       g   R# \        V P                  R4      \	        V4      4      '       d   R# V# )zSRecord's PID when it is alive and passes the start-time PID-reuse guard, else None.Nr!  )r`  Ú_pid_existsre  râ   rO  )rß   rD  s   & r$   Ú_live_pid_from_recordri  x  sB   € ä
˜6Ó
"€CØ
‚{œ+ c×*Ò*ÙÜ˜VŸZ™Z¨Ó5Ô7NÈsÓ7S×TÒTÙØ€Jr'   c                ó   € V ^8„  d   QhRR/# rh   ri   )r"   s   "r$   r%   r%   ‚  s   € ÷ +ñ + $ñ +r'   c                  ó„   € \         ;_uu_ 4        \        P                  4        R R R 4       R #   + '       g   i     R # ; iru   )Ú_gateway_running_pid_cache_lockÚ_gateway_running_pid_cacheÚclearri   r'   r$   Ú_clear_running_pid_cachero  ‚  s#   € ß	(Ö	(Ü"×(Ñ(Ô*÷ 
)×	(×	(Ò	(ús   �.®?	c                óˆ   € V ^8„  d   QhR\         R\        \        \        \        ,          \        \        ,          3,          /# rÎ   )r   ÚtuplerP   r   r=   )r"   s   "r$   r%   r%   ‡  s.   € ÷ .ñ .¤ð .¬¬t´X¼cµ]ÄHÌSÅMÐ/QÕ)Rñ .r'   c                 ó|   €  V P                  4       pRTP                  TP                  3#   \         d    Ru # i ; i)FT)FNN)Ústatr.  Úst_mtime_nsÚst_size)r:   Ústs   & r$   Ú_file_cache_signaturerw  ‡  s@   € ð#Ø�Y‰Y‹[ˆð �"—.‘. "§*¡*Ð-Ð-øô ô #Ø"Ò"ð#ús   ‚+ «;º;Úunlink_lockTc                ó@   € V ^8„  d   QhR\         R\        R\        RR/# )r   r  Úcleanup_stalerx  r<   N©r   rP   )r"   s   "r$   r%   r%   �  s,   € ÷ )ñ )Üð)Ü&*ð)Ü9=ð)à	ñ)r'   c               óä   € V'       g   R# \        4        V 3 F@  p\        P                  ! \        4      ;_uu_ 4        VP	                  RR7       RRR4       KB  	  R#   + '       g   i     KW  ; i)a  Force-unlink a stale PID file (lock confirmed inactive, so no pid check). The sibling lock
file is never unlinked, held or not (``unlink_lock`` is therefore moot): another contender may
already have opened that inode, and a fresh one would let two processes each hold "the" lock.NTrM  )ro  rð   rñ   rÂ   rO  )r  rz  rx  r:   s   &$$ r$   Ú_cleanup_invalid_pid_pathr}  �  sM   € ÷ ÙÜÔà“ˆÜ× Ò ¤×+Õ+Ø�K‰K 4ˆKÔ(÷ ,Ñ+ó ß+×+Ð+ús   ½AÁA/c                ó$   € V ^8„  d   QhR\         /# r‡   ©rP   )r"   s   "r$   r%   r%   ž  s   € ÷ ñ ¤dñ r'   c                 ó"  €  \         '       d¢   V P                  ^ \        P                  4       V P	                  4       ^ 8X  d"   V P                  R4       V P                  4        V P                  \        4       \        P                  ! V P                  4       \        P                  ^4       R# \        P                  ! V P                  4       \        P                  \        P                  ,          4       R#   \         \"        3 d     R# i ; i)rg  r¨   TF)rN  Úseekr¾   ÚSEEK_ENDÚtellÚwritera   Ú_WINDOWS_LOCK_OFFSETÚmsvcrtÚlockingÚfilenoÚLK_NBLCKÚfcntlÚflockÚLOCK_EXÚLOCK_NBÚBlockingIOErrorr.  ©Úhandles   &r$   Ú_try_acquire_file_lockr‘  ž  sª   € ðß‹;Ø�K‰K˜œ2Ÿ;™;Ô'Ø�{‰{‹} Ô!Ø—‘˜TÔ"Ø—‘”Ø�K‰KÔ,Ô-Ü�NŠN˜6Ÿ=™=›?¬F¯O©O¸QÔ?ñ ô �KŠK˜Ÿ™›¬¯©¼¿¹Õ)FÔGÙøÜœWÐ%ô Úðús   ‚C9 ŽBC9 Â/AC9 Ã9DÄDc                ó0   € V ^8„  d   QhR\         R\        /# r�  rÚ  )r"   s   "r$   r%   r%   ®  s   € ÷ "ñ "”Sð "œTñ "r'   c                óp  € \        V 4      p  ^ RIp\        P                  R8g  p V'       d1   VP	                  V 4      P                  4       VP                  8X  d   R# \        TP                  T 4      4      #   \        TRR4       d     R# \         d     L;i ; i  \         d     Mi ; i\        T 4      # )al  Cross-platform "is this PID alive" check that does NOT kill the target. CRITICAL on Windows:
``os.kill(pid, 0)`` sends ``CTRL_C_EVENT`` to the whole console group (bpo-14484), so prefer
psutil, then ctypes ``OpenProcess`` (Windows) / ``os.kill(pid, 0)`` (POSIX). Zombies report
dead: treating one as alive makes --replace wait forever under systemd Restart=always.NÚntFÚNoSuchProcessri   )r=   r‰  r¾   rB   rŒ  r:  ÚSTATUS_ZOMBIErU  rÂ   rP   Ú
pid_existsÚImportErrorr   )rD  r‰  Úprobe_zombies   &  r$   rh  rh  ®  s®   € ô
 ˆc‹(€CðÛô
 —w‘w $‘ˆð	÷  §¡¨sÓ 3× :Ñ :Ó <À×@TÑ@TÔ TÙô
 �F×%Ñ% cÓ*Ó+Ð+øô	 �v˜°Ó3ô 	ÚÜô 	Ùð	ûô ô Ùðúä˜SÓ!Ð!sF   �B ¥6A7 ÁB Á7BÂ	B ÂBÂBÂB ÂBÂB ÂB*Â)B*c                ó   € V ^8„  d   QhRR/# rh   ri   )r"   s   "r$   r%   r%   Ð  s   € ÷ 8ñ 8 $ñ 8r'   c                 ó–  € \         P                  ! \        4      ;_uu_ 4        \        '       dK   V P	                  \
        4       \        P                  ! V P                  4       \        P                  ^4       M3\        P                  ! V P                  4       \        P                  4       RRR4       R#   + '       g   i     R# ; i)r?   N)rð   rñ   r.  rN  r�  r…  r†  r‡  rˆ  ÚLK_UNLCKrŠ  r‹  ÚLOCK_UNr�  s   &r$   Ú_release_file_lockrž  Ð  sf   € Ü	×	Ò	œW×	%Õ	%ß‹;Ø�K‰KÔ,Ô-Ü�NŠN˜6Ÿ=™=›?¬F¯O©O¸QÕ?ä�KŠK˜Ÿ™›¬¯©Ô7÷ 
&×	%×	%Ò	%ús   £B
B7Â7C	c                ó$   € V ^8„  d   QhR\         /# r‡   r  )r"   s   "r$   r%   r%   Ù  s   € ÷ ñ ¤dñ r'   c                 óˆ   € ^ RI Hp Hp  V P                  \	        4       .4       \        4        R#   T\
        3 d     R# i ; i)zFReserve the launch profile without unlinking inaccessible lock inodes.©Úprocess_ownershipÚOwnershipConflictFT)Úgateway.runtime_ownershipr¢  r£  ÚreserverÌ   r.  ro  r¡  s     r$   Úacquire_gateway_runtime_lockr¦  Ù  sC   € çNðØ×!Ñ!Ô#;Ó#=Ð">Ô?ô ÔÙøð œwÐ'ô Úðús   Š0 °AÁ Ac                ó   € V ^8„  d   QhRR/# rh   ri   )r"   s   "r$   r%   r%   ã  s   € ÷ ñ  dñ r'   c                 óF   € ^ RI Hp  V P                  4        \        4        R# )zIRelease only this process's profile reservations, never their lock files.©r¢  N)r¤  r¢  Úclosero  r©  s    r$   Úrelease_gateway_runtime_lockr«  ã  s   € å;Ø×ÑÔÜÖr'   c                ó$   € V ^8„  d   QhR\         /# r‡   r  )r"   s   "r$   r%   r%   é  s   € ÷ >ñ >¤4ñ >r'   c                  ó@   € ^ RI Hp  V P                  \        4       4      # )rg  r©  )r¤  r¢  ÚownsrÌ   r©  s    r$   Úowns_gateway_runtime_lockr¯  é  s   € Ý;Ø×!Ñ!Ô":Ó"<Ó=Ð=r'   c                ó$   € V ^8„  d   QhR\         /# r‡   r  )r"   s   "r$   r%   r%   í  s   € ÷ 	ñ 	¤ñ 	r'   c           	     ó�  €  \        V 4      '       * pV'       g   \        V 4       V\        P                  ! \        4      ;_uu_ 4        V P                  4        RRR4       #   + '       g   i     # ; i  \        P                  ! \        4      ;_uu_ 4        T P                  4        RRR4       i   + '       g   i     i ; i; i)zVTrue when another process holds the lock (a won probe is released); closes ``handle``.N)r‘  rž  rð   rñ   r.  rª  )r�  Úhelds   & r$   Ú_probe_lock_filer³  í  ss   € ðÜ)¨&Ó1Ô1ˆßÜ˜vÔ&Øä× Ò ¤×)Õ)Ø�L‰LŒN÷ *×)×)Ð)ûŒZ× Ò ¤×)Õ)Ø�L‰LŒN÷ *×)×)Ð)ýs/   ‚$A5 ÁA"Á"A2Á5#CÂB2	Â)	CÂ2CÂ=Cc                óF   € V ^8„  d   QhR\         \        ,          R\        /# rV  )r   r   rP   )r"   s   "r$   r%   r%   ù  s   € ÷ $ñ $¬h´t­nð $Ìñ $r'   c                óô   € T ;'       g    \        4       p\        4       '       d   V\        4       8X  d   R# VP                  4       '       g   R#  \        VRRR7      p\        T4      #   \         d     R# i ; i)z?True when some process currently owns the gateway runtime lock.TFza+r°   r¦   )r  r¯  rµ   Úopenrˆ  r³  )rW  Úresolved_lock_pathr�  s   &  r$   Úis_gateway_runtime_lock_activer¸  ù  ss   € à"×>Ð>Ô&<Ó&>ÐÜ ×"Ò"Ð'9Ô=SÓ=UÔ'UÙØ×$Ñ$×&Ò&ÙðÜÐ(¨$¸ÔAˆô ˜FÓ#Ð#øô ô âðús   ÁA( Á(A7Á6A7c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   r:   Úlabelr<   rØ   )r"   s   "r$   r%   r%     s&   € ÷ Sñ Sœdð S¬3ð S´4ñ Sr'   c                óŠ   €  V P                  4        R#   \         d     R# \         d   p\        T RT 24      ThRp?ii ; i)zWLike ``path.exists()`` but raises RuntimeError instead of False on EACCES-style errors.TFz metadata is not inspectable: N)rs  rY  r.  ÚRuntimeError)r:   rº  rs   s   && r$   Ú_strict_path_existsr½    sJ   € ðSØ�	‰	ŒÙøÜô ÚÜô SÜ˜e˜WÐ$BÀ3À%ÐHÓIÈsÐRûðSús   ‚ ”A¢A«A¬=½Ac                ó0   € V ^8„  d   QhR\         R\        /# rV  r{  )r"   s   "r$   r%   r%     s   € ÷ Qñ Q´dð Q¼tñ Qr'   c                óÚ   €  \        V RRR7      p \	        T4      #   \         d     R# \         d   p\        RT 24      ThRp?ii ; i  \         d   p\        RT 24      ThRp?ii ; i)z<Probe ownership without treating access failures as absence.zr+r°   r¦   Fz)gateway runtime lock is not inspectable: Nz#gateway runtime lock probe failed: )r¶  rY  r.  r¼  r³  )rW  r�  rs   s   &  r$   Ú&_is_gateway_runtime_lock_active_strictrÀ    s„   € ðWÜ�i °Ô8ˆð
QÜ Ó'Ð'øô ô ÚÜô WÜÐFÀsÀeÐLÓMÐSVÐVûðWûô ô QÜÐ@ÀÀÐFÓGÈSÐPûðQús5   ‚ ‘
A œAªA³A´AÁAÁA*ÁA%Á%A*c                ó   € V ^8„  d   QhRR/# rh   ri   )r"   s   "r$   r%   r%   !  s   € ÷ ñ ˜ñ r'   c                 ó†   € \        4       p \        V P                  RRR7       \        V \	        4       4       \        4        R# )z{Write this process's PID record via O_CREAT|O_EXCL; a racing gateway's FileExistsError
propagates for the caller to decide.Tr¢   N)rÿ   r   r²   Ú_write_json_exclr#  ro  rÓ   s    r$   Úwrite_pid_filerÄ  !  s/   € ô ‹?€DÜ�$—+‘+ t°dÕ;Ü�TÔ,Ó.Ô/ÜÖr'   c                óV   € V ^8„  d   QhR\         R\        \        \        3,          RR/# ©r   r:   rß   r<   Nr�   )r"   s   "r$   r%   r%   *  s)   € ÷ ñ œ4ð ¬¬c´3¨h­ð ¸Dñ r'   c                ó„  € \         P                  ! V \         P                  \         P                  ,          \         P                  ,          4      p \         P
                  ! VRRR7      ;_uu_ 4       p\        P                  ! W4       RRR4       R#   + '       g   i     R# ; i  \         d    \        T 4       h i ; i)zSCreate ``path`` with O_CREAT|O_EXCL and dump ``record``; unlinks on a failed write.Úwr°   r¦   N)
r¾   r¶  ÚO_CREATÚO_EXCLÚO_WRONLYÚfdopenrB  ÚdumprÂ   rP  )r:   rß   Úfdr�  s   &&  r$   rÃ  rÃ  *  sv   € ä	�Š�”r—z‘z¤B§I¡IÕ-´·±Õ;Ó	<€BðÜ�YŠY�r˜3¨×1Õ1°VÜ�IŠI�fÔ%÷ 2×1×1Ò1ûäô Ü˜ÔØðús*   Á!B' Á2BÂ	B' ÂB$	ÂB' Â$B' Â'B?c                óJ   € V ^8„  d   QhR\         \        \        3,          RR/# )r   r@   r<   Nr%  )r"   s   "r$   r%   r%   5  s&   € ÷ Iñ Iœd¤3¬ 8�nð I¸ñ Ir'   c                óV   € V F"  w  r#pV\         Jg   K  Ve	   V! V4      MTW&   K$  	  R# )zXAssign each ``(key, value, coerce)`` whose value was explicitly passed (not ``_UNSET``).N)Ú_UNSET)r@   Úfieldsr\  r   Úcoerces   &&   r$   Ú_apply_set_fieldsrÔ  5  s+   € ã$Ñˆ�FØœÕØ+1Ò+=™& œ-À5ˆF‹Kó %r'   c                óR   € V ^8„  d   QhR\         R\        \        \        3,          /# )r   r9  r<   )r   r    r!   )r"   s   "r$   r%   r%   <  s&   € ÷ Zñ Z¬ð Z´´c¼3°hµñ Zr'   c                 ó–   € \        V \        4      '       d%   \        V P                  R 4      ;'       g    R4      MRpR VR9   d   V/# R/# )r:  r  r;  >   ÚokÚretryingÚunavailable)r„   r    r!   râ   )r9  rZ   s   & r$   Ú_coerce_session_storerÚ  <  sJ   € Ü6@ÀÔPT×6UÒ6UŒC�×!Ñ! (Ó+×1Ð1¨rÔ2Ð[]€EØ˜uÐ(IÔI�eÐYÐYÈyÐYÐYr'   r:  r=  r6  r7  Úactive_workÚplatformÚplatform_stateÚ
error_codeÚerror_messageÚneeds_attentionÚretrying_sinceÚserved_profilesr9  Úparked_profilesÚmultiplex_standalone_reasonÚplatform_metricsÚingress_urlÚlistener_baseÚclear_profile_platformsÚdrop_profile_platformsÚload_existingÚreload_existingc          3      ó²  € V ^8„  d   QhR\         R\         R\         R\         R\         R\         R\         R\         R	\         R
\         R\         R\         R\         R\         R\         R\         R\         R\         R\        R\        \        ,          R\        R\        R\        \
        \        \        \         3,          \        \        \         3,          3,          /# )r   r:  r=  r6  r7  rÛ  rÜ  rÝ  rÞ  rß  rà  rá  râ  r9  rã  rä  rå  ræ  rç  rè  ré  rê  rë  r<   )r   rP   r   r!   rq  r   r    )r"   s   "r$   r%   r%   A  s%  € ÷ E/ñ E/ÜðE/Ü14ðE/ÜRUðE/äðE/ä.1ðE/äFIðE/ädgðE/ô ðE/ô .1ðE/ô MPðE/ô ð	E/ô 47ð	E/ô QTð	E/ô
 ðE/ô
 ADðE/ô ðE/ô ðE/ô /2ðE/ô VZðE/ô %¤S�MðE/ô ðE/ô 26ðE/ô Œ4””cœ3�h•¤¤c¬3 h¥Ð/Õ0ñE/r'   c                ó´  € \        4       p\        ;_uu_ 4        V'       g   \        V8w  g	   \        f*   VsV'       d   \	        V4      MR;'       g    \        4       s\        p\        P                  ! V4      p\        4       pVP                  R/ 4       \        VR,          \        4      '       g   / VR&   V'       g	   V'       d|   V'       d   V R2MRpVR,          P                  4        UUu/ uFE  w  pp\        V\        4      '       d'   RV9  g    Vf   K)  VP                  V4      '       d   KB  VVbKG  	  uppVR&   TP                  R Uu/ uF  pVVV,          bK  	  up4       \!        4       VR&   VP                  \#        4       4       \%        VRV R3RVR3R	V\&        3R
V\(        3RVR 3RVR 3RVR 3RVR 3RV\*        33	4       V\,        JdÏ   \        P                  ! VR,          P/                  V/ 4      4      p\        V\        4      '       g   / pVR8X  d   V	\,        J d   RMT	p	V
\,        J d   RMT
p
\%        VRVR3RVR3RVR3RV	\&        3RV
R3RVR3RVR3RVR334       VP                  \!        4       VR,          VR,          R7       VVR,          V&   VsVVV3uuRRR4       # u uppi u upi   + '       g   i     R# ; i) zAMerge one update into the process-wide canonical status snapshot.Nr8  rJ  rD  r!  r<  r:  r=  r6  r7  rÛ  c                 ó,   € V '       d   \        V 4      # R # ru   ©rå  ©Úvs   &r$   Ú<lambda>Ú0_prepare_runtime_status_update.<locals>.<lambda>j  s   € ¿a´4¸³7Ð3IÀTÐ3Ir'   râ  c                 ó,   € \        T ;'       g    . 4      # ru   rï  rð  s   &r$   rò  ró  k  s   € ¼4ÀÇÀÀR¼=r'   rã  c                 ó¢   € \        T ;'       g    / 4      P                  4        UUu/ uF  w  r\        V4      \        V4      bK  	  upp# u uppi ru   )r    Úitemsr!   )rñ  Úkri  s   &  r$   rò  ró  m  s?   € ÔW[Ð\]×\cÐ\cÐacÓWd×WjÑWjÔWlÔ;mÑWlÉtÈq¼CÀ»FÄCÈÃFºNÑWlÓ;mùÓ;ms   § Arä  c                 ó,   € V '       d   \        V 4      # R # ru   r  rð  s   &r$   rò  ró  n  s   € ×]^ÔSVÐWXÓSYÐShÐdhÐShr'   r9  Ú	connectedFrZ   rÞ  rß  rà  rá  Úmetricsræ  rç  )r<  Ú
writer_pidÚwriter_start_time)rà  rD  rß  r!  )r  r‰   Ú_runtime_status_state_pathÚ_runtime_status_staterƒ   r=  rC   rD   r#  Ú
setdefaultr„   r    rö  r!   r¿  Úupdater  r-  rÔ  rP   Úparse_active_agentsrÚ  rÑ  râ   )r:  r=  r6  r7  rÛ  rÜ  rÝ  rÞ  rß  rà  rá  râ  r9  rã  rä  rå  ræ  rç  rè  ré  rê  rë  r:   Úprevious_payloadr;   Úcurrent_recordÚdrop_prefixr÷  rñ  r\  Úplatform_payloads   $$$$$$$$$$$$$$$$$$$$$$         r$   Ú_prepare_runtime_status_updater  A  sò  € ô $Ó%€Dß	#Ö	#ßÔ8¸DÔ@ÔDYÒDaØ)-Ð&ç*7” Ô&¸T×dÐdÔFbÓFdð "ô 1ÐÜ—-’-Ð 0Ó1ˆÜ*Ó,ˆØ×Ñ˜;¨Ô+Ü˜' +Õ.´×5Ò5Ø#%ˆG�KÑ ß"×&<ß:PÐ3Ð4°AÑ6ÐVZˆKà!(¨Õ!5×!;Ñ!;Ô!=ô$Ù!=™˜˜AÜ! !¤S×)Ò)¨S¸¬\Øô à45·L±LÀ×4Mô ��1’Ñ!=ò$ˆG�KÑ ð
 	�‰Ñ<aÓbÑ<a°S˜˜^¨CÕ0Ò0Ñ<aÑbÔcÜ ,£ˆ�ÑØ�‰Ô0Ó2Ô3Ü˜'Ø˜m¨TÐ2°]ÀKÐQUÐ4VØ Ð"3´TÐ:Ø˜mÔ-@ÐAØ˜KÑ)IÐJØ Ñ1HÐIà Ñ1mÐnØ*Ð,GÑIhÐiØ˜mÔ-BÐCð
$
ô 
	ð œ6Ó!Ü#Ÿ}š}¨W°[Õ-A×-EÑ-EÀhÐPRÓ-SÓTÐÜÐ.´×5Ò5Ø#%Ð Ø Ô,Ø+:¼fÓ+D¡%È/�Ø)7¼6Ó)A¡À~�ÜÐ.Ø˜.¨$Ð/°,À
ÈDÐ1QØ  -°Ð6Ø" O´TÐ:Ø! >°4Ð8ØÐ,¨dÐ3Ø ¨TÐ2Ø  -°Ð6ð1ô ð ×#Ñ#Ü'›>°nÀUÕ6KØ"0°Õ">ð $ô @ð .>ˆG�KÕ  Ñ*Ø 'ÐØ�WÐ.Ð.÷o 
$Ò	#ùó$ùò
 c÷) 
$×	#Ð	#úsT   ™%K¿KÁA,KÃ KÃKÃ!KÃ1&J;
ÄJ;
Ä5J;
Ä<KÅKÅ%EKÊ;KËK	c                óx   € V ^8„  d   QhR\         \        \        3,          R\         \        \        3,          RR/# )r   r  r;   r<   Nr%  )r"   s   "r$   r%   r%   ‰  s9   € ÷ Bñ BÜœ3¤˜8•nðBÜ/3´C¼°H­~ðBà	ñBr'   c                 ó    € \         P                  ! \        4      ;_uu_ 4        ^ RIHp V! W4       RRR4       R#   + '       g   i     R# ; i)rg  )Úemit_runtime_status_transitionN)rð   rñ   rÂ   Úagent.monitoring.gateway_healthr	  )r  r;   r	  s   && r$   Ú_emit_runtime_status_transitionr  ‰  s0   € ô 
×	Ò	œY×	'Õ	'ÝRÙ&Ð'7ÔA÷ 
(×	'×	'Ò	'ús	   £<¼A	Úwait_timeoutc                ó^   € V ^8„  d   QhR\         R\        \        ,          R\        R\         /# )r   rë  r  rÒ  r<   )rP   r   rO   r   )r"   s   "r$   r%   r%   �  s0   € ÷ 9ñ 9Üð9Ü4<¼UµOð9ÜVYð9ä	ñ9r'   c                óê   € \         ;_uu_ 4        \        RRV /VB w  r4p\        4       pVP                  W44      pRRR4       \	        XX4       XP                  XVR7      #   + '       g   i     L/; i)a  Synchronously persist status for CLI callers and off-loop startup.

``wait_timeout`` bounds how long the caller waits for durable persistence.
A timed-out update remains queued for the single background writer.
Keyword ``fields`` are those of ``_prepare_runtime_status_update``.
rë  NrS   ri   )r‰   r  r‹   rK   r  rX   )rë  r  rÒ  r:   r;   r  r�   rJ   s   $$,     r$   Úwrite_runtime_statusr  �  sn   € ÷ 
$Ö	#Ü*Hñ +7Ø+ð+7Ø/5ñ+7Ñ'ˆÐ'ä+Ó-ˆØ—]‘] 4Ó1ˆ
÷	 
$ô $Ð$4°gÔ>Ø�;‰;�z¨<ˆ;Ó8Ð8÷ 
$×	#ús   �,A"Á"A2	c                ó0   € V ^8„  d   QhR\         R\        /# )r   rÒ  r<   ©r   r=   )r"   s   "r$   r%   r%   ¤  s   € ÷ 
ñ 
¤Sð 
¬Sñ 
r'   c                 óÄ   € \         ;_uu_ 4        \        RRR/V B w  rp\        4       P                  W4      pRRR4       \	        XX4       X#   + '       g   i     L; i)zŠMerge and enqueue status without waiting for filesystem persistence.

Keyword ``fields`` are those of ``_prepare_runtime_status_update``.
rê  FNri   )r‰   r  r‹   rK   r  )rÒ  r:   r;   r  rJ   s   ,    r$   Úpublish_runtime_statusr  ¤  s^   € ÷
 
$Ö	#Ü*Hñ ++Øð++Ø#)ñ++Ñ'ˆÐ'ä/Ó1×8Ñ8¸ÓGˆ
÷ 
$ô $Ð$4°gÔ>ØÐ÷ 
$×	#ús   �*AÁA	c                ó~   € V ^8„  d   QhR\         \        ,          R\         \        \        \        3,          ,          /# rÎ   rX  )r"   s   "r$   r%   r%   ±  s+   € ÷ ?ñ ?œh¤t�nð ?¼ÄÄcÌ3ÀhÅÕ8Pñ ?r'   c                ó<   € \        T ;'       g    \        4       4      # )zRRead ``gateway_state.json``; ``path`` lets callers inspect another profile's file.)rƒ   r  rÓ   s   &r$   Úread_runtime_statusr  ±  s   € ä˜4×=Ð=Ô#;Ó#=Ó>Ð>r'   c                ót   € V ^8„  d   QhR\         \        \        \        3,          ,          R\        R\
        /# )r   rß   Úttl_sr<   )r   r    r!   r   r=   rP   )r"   s   "r$   r%   r%   ½  s6   € ÷ cñ cÜ”Tœ#œs˜(•^Õ$ðcÜ-0ðcä	ñcr'   c                ó†   € \        V \        4      '       * ;'       g&    \        V P                  R4      ;'       g    RV4      # )zYTrue when the snapshot's ``updated_at`` is older than ``ttl_s`` (or missing/unparseable).r<  r  )r„   r    Ú_marker_is_stalerâ   )rß   r  s   &&r$   Úruntime_status_is_staler  ½  s7   € ô ˜&¤$Ó'Ô'×bÐbÔ+;¸F¿J¹JÀ|Ó<T×<ZÐ<ZÐXZÐ\aÓ+bÐbr'   c                ó~   € V ^8„  d   QhR\         \        \        \        3,          ,          R\         \        ,          /# r÷   r]  )r"   s   "r$   r%   r%   Ä  s0   € ÷ añ a¬8´D¼¼c¸µNÕ+Cð aÌÔQTÍñ ar'   c           	     ó&  € \        V \        4      '       d   \        V P                  R4      4      MRpV'       g   R# \	        ^ \        \        P                  ! \        4      \        P                  ! V4      ,
          P                  4       4      4      # )z’Whole seconds since the snapshot's ``updated_at``; None when missing/unparseable (an
unparseable stamp is a stale *file*, not a wedged heartbeat).r<  N)r„   r    r2  râ   rV   r=   r   r³   r   r(  Útotal_seconds)rß   r<  s   & r$   Úruntime_status_heartbeat_age_sr  Ä  sd   € ô DNÈfÔVZ×C[ÒC[Ô% f§j¡j°Ó&>Ô?Ðae€JßÙÜˆq”#”x—|’|¤CÓ(¬8×+AÒ+AÀ*Ó+MÕM×\Ñ\Ó^Ó_Ó`Ð`r'   c                óh   € V ^8„  d   QhR\         \        \        \        3,          ,          R\        /# r÷   r/  )r"   s   "r$   r%   r%   Í  s'   € ÷ 5ñ 5¤x´´S¼#°XµÕ'?ð 5ÄDñ 5r'   c                ó   € \        V 4      RJ# )zPTrue when the snapshot's PID is alive and passes the start-time PID-reuse guard.N)ri  )rß   s   &r$   Úruntime_status_pid_is_liver"  Í  s   € ä  Ó(°Ð4Ð4r'   c                ó0   € V ^8„  d   QhR\         R\        /# )r   r/  r<   r  )r"   s   "r$   r%   r%   Ò  s   € ÷ ñ œSð ¤Sñ r'   c                ó^   €  \        ^ \        V 4      4      #   \        \        3 d     ^ # i ; i)zWCoerce ``active_agents`` to a non-negative int; shared by writer and both HTTP readers.)rV   r=   rQ  rº   )r/  s   &r$   r  r  Ò  s/   € ðÜ�1”c˜#“hÓÐøÜ”zÐ"ô Úðús   ‚ —,«,Úrunningr<  c                óH   € V ^8„  d   QhR\         R\        R\        R\         /# )r   Úgateway_runningr:  r7  r<   ©rP   r   )r"   s   "r$   r%   r%   ß  s*   € ÷ 2ñ 2¬Dð 2Äð 2ÔUXð 2Ô]añ 2r'   c                óF   € \        WR7      '       g   R# \        V4      ^ 8„  # )zÚBusy iff live, serving (``running``/``degraded``), and ``active_agents > 0`` -- the contract NAS gates on. Liveness
keys off ``gateway_running``, NEVER ``updated_at`` (a stale heartbeat is a health warning, not death).©r'  r:  F)Úderive_gateway_drainabler  )r'  r:  r7  s   $$$r$   Úderive_gateway_busyr,  ß  s"   € ô $°O×aÓaÙÜ˜}Ó-°Ñ1Ð1r'   c                ó<   € V ^8„  d   QhR\         R\        R\         /# )r   r'  r:  r<   r(  )r"   s   "r$   r%   r%   ç  s&   € ÷ Pñ P´ð PÄcð PÌdñ Pr'   c                ó:   € \        V 4      ;'       d
    V\        9   # )zVDrainable iff live and serving; independent of ``active_agents`` (idle drains finish).)rP   Ú_DRAINABLE_GATEWAY_STATESr*  s   $$r$   r+  r+  ç  s   € ä�Ó ×OÐO ]Ô6OÑ%OÐOr'   )Úfrozenc                   ó<   a € ] tR tRt o RtRtRtRtV 3R ltRt	V t
R# )ÚGatewayLivenessiì  a  Resolved gateway liveness for one dashboard surface. ``source``: which ladder rung answered
(logging/tests; product code reads it only via ``status_served.local_liveness_pid``).
``probe_error``: a rung raised; lets fail-open callers tell "down" from "unknown".NFc                ó¾   <€ V ^8„  d   Qh/ S[ ;R&   S[S[,          ;R&   S[;R&   S[S[S[S[3,          ,          ;R&   S[ ;R&   S[S[S[S[3,          ,          ;R&   # )r   r%  rD  ÚsourceÚhealth_bodyÚprobe_errorr6  )rP   r   r=   r!   r    r   )r"   r#   s   "€r$   r%   ÚGatewayLiveness.__annotate__ì  so   ø‡ ‚ ñ �Mñ ñ 
‘#�Ññ ñ �Kñ ñ ™$™s¡C˜x�.Õ)Ñ0ñ ñ Ññ ñ ‘d™3¡˜8•nÕ%Ñ,ò r'   ri   )rx   ry   rz   r{   r|   r5  r6  r6  r�   r}   r~   r   s   @r$   r2  r2  ì  s%   ø‡ € ñZð -1€KØ€Kð )-€G÷ ƒ r'   r2  c                óF   € V ^8„  d   QhR\         R\        \        ,          /# rè  rê  )r"   s   "r$   r%   r%   ý  s   € ÷ ñ ¬ð ´¼#µñ r'   c                óà   € \        V 4      p\        V4      pV'       d   V#  ^ RIHp VP	                  4       \        V! 4       4      P	                  4       8X  d   R#  R#   \
         d     R# i ; i)uð   Profile id of any Hermes home: ``<root>/profiles/<name>`` â†’ ``<name>``, the default root â†’
``"default"``, anything else â†’ None. Multiplex-only makes ``default`` an ordinary served
profile, so reporting surfaces need a name for it too.©rï   rë   N)r   rì  rî   rï   rÒ   rÂ   )ré  rè   Únamedrï   s   &   r$   r  r  ý  sj   € ô �Ó€DÜ" 4Ó(€EßØˆðÝ<Ø�<‰<‹>œTÑ"9Ó";Ó<×DÑDÓFÔFÙð Gñ øô ô Úðús   ¢7A ÁA-Á,A-c          	      óŠ   € V ^8„  d   QhR\         R\        \        \        \        \
        \        3,          3,          ,          /# )r   Úprofile_dirr<   )r   r   rq  r=   r    r!   r   )r"   s   "r$   r%   r%     s8   € ÷ $Nñ $N´$ð $N¼8ÄEÌ#ÌtÔTWÔY\ÐT\Í~ÐJ]ÕD^Õ;_ñ $Nr'   c                óæ  € \        \        V 4      4      pV'       g   R# ^ RIHp ^ RIHp ^ RIHp ^ RIH	p VR8w  d'   \        W! 4       R,          V,          4      '       g   R# V! 4       pV! 4       pVe;   VP                  V4      '       d$   VP                  pVP                  ;'       g    TpMVR8w  d   V! V4      '       d	   V! 4       pMR# Vf   R# T\        VR,          4      ;'       g    / 3# )	uz  ``(pid, host gateway_state.json)`` when the ONE live host gateway serves the profile whose home
is ``profile_dir``; None for a home it does not serve or when no gateway owns the host role.

Multiplex-only: ``default`` is just another served profile, not the owner of a private topology â€”
resolving from the host rendezvous record (``gateway/host_topology.py``) is what lets it be
reported as SERVED rather than only as owner. A served profile owns no
``gateway.pid``/``gateway_state.json`` (#97120), so every PID-file rung of the dashboard ladder
reports it stopped while ``hermes -p X status`` says running â€” the two must agree.
N)Úhost_gateway_topology)Ú+named_profile_served_by_running_multiplexer)Úlive_default_gateway_pidr:  rë   rê   r   )r  r   Úgateway.host_topologyr?  Úhermes_cli.gatewayr@  Ú#hermes_cli.gateway_multiplex_servedrA  rî   rï   rÜ   r  rD  rè   r  )	r=  rB   r?  r@  rA  rï   ÚtopologyÚlaunch_homerD  s	   &        r$   Ú multiplexer_liveness_for_profilerG    sÔ   € ô !¤ kÓ!2Ó3€DßÙÝ;ÝNÝLÝ8ð ˆyÔÔ!2°;Ð@WÓ@YÐ\fÕ@fÐimÕ@m×!nÒ!nÙÙ$Ó&€Hñ *Ó+€KØÒ §¡°× 5Ò 5Ø%Ÿ\™\ˆØ—m‘m×2Ð2 {‰Ø	�Ô	ÑJÈ4×PÒPá&Ó(‰áØ
‚{ÙØÔ# KÐ2FÕ$FÓG×MÐMÈ2ÐMÐMr'   c                ó–   € V ^8„  d   QhR\         \        \        \        3,          ,          R\        R\        \        \        3,          /# ©r   r6  rú   r<   rø   )r"   s   "r$   r%   r%   5  s<   € ÷ ñ ¬h´t¼CÄ¸Hµ~Õ.Fð ÔQTð ÔY]Ô^aÔcfÐ^fÕYgñ r'   c                óp  € ^ RI HpHp T ;'       g    / P                  R4      pV'       d   VR8X  g   \	        V\
        4      '       g   / # / p\        V4       FÔ  pVP                  V4      p\	        V\
        4      '       d   VP                  R4      R
9  d   KB  VP                  R4      p\	        V\        4      '       d"   V'       d   V RV VP                  VR4       2MRp	VP                  4        U
Uu/ uF  w  r«V
R8w  g   K  W«bK  	  upp
WV&   WV,          P                  V	RR	7       KÖ  	  V# u upp
i )u  Entries for the api_server/webhook mirrors a served ``profile`` gets from the DEFAULT's
listener. The multiplexer never builds those adapters for a secondary (``gateway.run_adapters``
skips them: ``SHARED_LISTENER_MIRROR_PLATFORMS``), so the record has no ``<profile>:api_server``
entry and every reader fell through to ``pending_restart`` â€” "Restart needed" forever while
``/p/<profile>/v1/...`` answered. Only a live default entry is mirrored; its state is the profile's
state, plus the ``/p/<profile>`` URL the client must actually call.
)ÚSHARED_LISTENER_MIRROR_PATHSÚ SHARED_LISTENER_MIRROR_PLATFORMSr8  rë   rZ   rç  z/p/r  N)ræ  Úmirrored_from>   rØ  rù  Ú
connecting)
Úgateway.configrK  rL  râ   r„   r    Úsortedr!   rö  r   )r6  rú   rK  rL  ÚplatsÚmirroredrB   r  rä   Úurlr÷  rñ  s   &&          r$   Ú shared_listener_mirror_platformsrT  5  s  € ÷ ^Ø�]ˆ]˜×Ñ Ó,€Eß�g Ô*´*¸UÄD×2IÒ2IØˆ	Ø!€HÜÐ7Ö8ˆØ—	‘	˜$“ˆÜ˜%¤×&Ò&¨%¯)©)°GÓ*<ÐDkÔ*kÙð �y‰y˜Ó)ˆÜS]Ð^bÔdg×ShÒSh×mq���c˜'˜Ð#?×#CÑ#CÀDÈ"Ó#MÐ"NÑOÐw{ˆØ+0¯;©;¬=ÔQ©=¡4 1¸AÀÑ<Pœ$˜!š$©=ÒQˆ‰Ø�×Ñ¨#¸YÐÖGñ 9ð €Oùó Rs   Ã7D2ÄD2c                ó–   € V ^8„  d   QhR\         \        \        \        3,          ,          R\        R\        \        \        3,          /# rI  rø   )r"   s   "r$   r%   r%   O  sA   € ÷ Iñ I´¼¼cÄ3¸h½Õ0Hð IÔSVð IÔ[_Ô`cÔehÐ`hÕ[iñ Ir'   c           
     ó€  € T ;'       g    / P                  R4      p\        V\        4      '       g   / # V R2pVP                  4        UUu/ uF]  w  rE\        V\        4      '       g   K  VP                  V4      '       g   K6  \        V\        4      '       g   KN  V\        V4      R VbK_  	  pppVR8X  dm   TP                  VP                  4        UUu/ uF@  w  rE\        V\        4      '       g   K  RV9  g   K&  \        V\        4      '       g   K>  WEbKB  	  upp4       / \        W4      CVC# u uppi u uppi )u0  The ``<profile>:<platform>`` entries of a multiplexer record, re-keyed to bare platform names â€” the
same shape a standalone gateway for ``profile`` writes into its own ``gateway_state.json`` â€” plus the
default listener's api_server/webhook mirrors the profile is served through (``ingress_url`` set).r8  rJ  Nrë   )	râ   r„   r    rö  r!   r¿  rÀ   r   rT  )r6  rú   rQ  Úprefixr\  r   Úowns   &&     r$   Ú"profile_platforms_from_multiplexerrY  O  s  € ð �]ˆ]˜×Ñ Ó,€EÜ�eœT×"Ò"Øˆ	Øˆy˜ˆ]€FØ6;·k±k´mô [±m©
¨Ü˜œc×"ô $Ø'*§~¡~°f×'=ô $ÜBLÈUÔTX×BYô $ˆ3Œs�6‹{ˆ|Ð˜eÒ#±m€Cñ [à�)Ôð
 	�
‰
°·±´ô \±¡: 3Ü! #¤s×+ô Ø03¸3±ô ÜCMÈeÔUY×CZô �C’J±ò \ô 	]àHÔ.¨wÓ@ÐHÀCÐHÐHùó[ùó\s0   ÁD4Á+D4ÂD4ÂD4ÃD:
Ã6D:
Ã?D:
ÄD:
r=  r6  Úhealth_probeÚ	use_cacheÚ	pid_probeÚruntime_readerÚruntime_pid_probec                ó  € V ^8„  d   QhR\         \        ,          R\        R\         \        . \        \
        \         \        \        \        3,          ,          3,          3,          ,          R\
        R\         \        R\         \        ,          3,          ,          R\         \        R\         \        \        \        3,          ,          3,          ,          R\         \        R\         \        ,          3,          ,          R	\        /# )
r   r=  r6  rZ  r[  r\  .r]  r^  r<   )
r   r   r   r	   rq  rP   r    r!   r=   r2  )r"   s   "r$   r%   r%   c  sÌ   € ÷ Nñ NÜœT•NðNÜ47ðNäœ8 B¬¬d´H¼TÄ#ÄsÀ(½^Õ4LÐ.LÕ(MÐ$MÕNÕOðNô ðNô (0´¸¼hÄs½mÐ9KÕ0LÕ'MðNô œX c¬8´D¼¼c¸µNÕ+CÐ&CÕDÕEð	Nô
  ¤¨¬h´s­mÐ);Õ <Õ=ðNô ñNr'   c                óÞ  a€ T;'       g    V'       d   \         M\        pT;'       g    \        pT;'       g    \        p	RoV RJp
RR/V3R llpV
'       d   V! WpR,          4      MV! V4      pVe   \	        RVRR7      # RpVe?   V! VRR	7      w  ríV'       d+   V'       d   VP                  R4      MRp\	        RVR
VR7      # V\        J d   V
'       d   RV R,          /M/ pV! V3/ VB pV
'       d   RV /M/ pT! Yš'       d   Vf   / MT3/ VB pVe   \	        RVRVR7      # V
'       d   T M	\        4       pV! \        V4      pVe   Vw  pp\	        RVRVVR7      # \	        RRRVSR7      # )uˆ  Single source of truth for "is the gateway up?" across dashboard surfaces. Ladder, most to
least authoritative: (1) PID file + runtime lock (scoped to ``profile_dir``; cached by default
so polling does not re-flock ``gateway.lock``); (2) caller-supplied HTTP health probe (gateway
in another container); (3) LOCAL runtime status PID validated against the live process table
with ``expected_home`` (a recycled PID of another profile never counts; pass ``runtime`` if
already read); (4) for a named ``profile_dir`` only, the live default multiplexer that records the
profile in ``served_profiles`` (a served profile writes no identity files of its own). ``*_probe``/
``runtime_reader`` are the dashboard's injection/test seam. A rung
that raises degrades to the next (never 500 a status endpoint) and sets ``probe_error``.

Before this existed, ``/api/status`` and ``/api/messaging/platforms`` each open-coded their own ladder
and disagreed on the same page load â€” the sidebar read "running" while the Channels page rendered "The
gateway is not running."  Three deployments hit it: a cross-container gateway (only ``/api/status`` ran
the HTTP health probe), a profile-scoped dashboard (only ``/api/status`` passed the profile's paths, so
messaging borrowed another profile's runtime state â€” issue #71211), and a launch-service-managed gateway
with no PID file (only some callers used the runtime-status fallback).
FNÚfallbackc                ó@   <€  V ! V/ VB #   \          d    R oTu # i ; i©T)rÂ   )Úfnra  ÚargsÚkwargsr6  s   &$*,€r$   ÚguardedÚ)resolve_gateway_liveness.<locals>.guarded�  s1   ø€ ð	Ù�tÐ&˜vÑ&Ð&øÜô 	ØˆKØŠOð	ús   ƒ ‹œrþ   TrD  )r%  rD  r4  )ra  Úhealth)r%  rD  r4  r5  r:   r   rÝ   Úruntime_statusÚmultiplexer)r%  rD  r4  r5  r6  Únone)r%  rD  r4  r5  r6  )FN)	Úget_running_pid_cachedÚget_running_pidr  Úget_runtime_status_running_pidr2  râ   rÑ  rÌ   rG  )r=  r6  rZ  r[  r\  r]  r^  Ú
_pid_probeÚ_runtime_readerÚ_runtime_pid_probeÚscopedrg  rD  r5  ÚaliveÚ
remote_pidÚreader_kwargsÚprobe_kwargsÚruntime_pidÚown_homeÚservedÚmux_pidÚmux_runtimer6  s   $$$$$$$                @r$   Úresolve_gateway_livenessr}  c  sœ  ø€ ð0 ×XÐX¿Õ5Ì€JØ$×;Ð;Ô(;€OØ*×LÐLÔ.LÐØ€KØ Ð$€Fð D÷ ÷ ?E‰'�*¨MÕ9Ô
:É'ÐR\ÓJ]€CØ
‚Ü t°¸UÔCÐCØ,0€KØÒÙ$ \¸MÔJÑˆßç3>˜Ÿ™¨Ô/ÀDˆJÜ"Ø *°XÈ;ôð ð ”&ÓßHN˜ Ð/CÕ!CÑDÐTVˆÙ˜/Ñ;¨]Ñ;ˆ÷ 6<�O [Ñ1À€LÙÐ,¶VÀÂ©bÐV]ÑnÐamÑn€KØÒÜØ˜kÐ2BÐP[ô
ð 	
÷ %‰{Ô*BÓ*D€HÙÔ5°xÓ@€FØÒØ%Ñˆ�ÜØ˜g¨mÈÐ^iô
ð 	
ô Ø˜4¨¸KÐU`ôð r'   c                ó    € V ^8„  d   QhR\         \        \        \        3,          ,          R\         \        ,          R\         \
        ,          /# )r   r6  rÝ   r<   )r   r    r!   r   r   r=   )r"   s   "r$   r%   r%   ´  s9   € ÷ ñ Ü”dœ3¤˜8•nÕ%ðÜ@HÌÅðäŒc…]ñr'   c               ó0  € V e   T M	\        4       p\        V\        4      '       g   R# VP                  R4      R9   d   R# \	        V4      pVf   R# Vf   \        V4      '       g   R# Ve   \        W!R7      '       d   R# \        W#VR7      '       g   R# V# )ad  Live gateway PID from the runtime status record, or None: the ``get_running_pid()`` fallback
for launch-service-managed gateways with a fresh ``gateway_state.json`` but no ``gateway.pid``.
``expected_home`` scopes the OS-identity check to another profile's home so a PID recycled onto
a different profile's gateway is not reported running for the dead one.Nr:  ©rÝ   >   Nr9  r;  )r  r„   r    râ   ri  r2  rå   r  )r6  rÝ   r;   rD  s   &$  r$   ro  ro  ´  sŠ   € ð !Ò,‰gÔ2EÓ2G€GÜ�gœt×$Ò$ÙØ‡{�{�?Ó#Ð'JÔJÙÜ
 Ó
(€CØ
‚{Ùð ÒÔ%KÈG×%TÒ%TÙØÒ Ô%DÀW×%jÓ%jÙÜ+¨GÈ×VÓVÙØ€Jr'   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# rç   )r   r   r=   )r"   s   "r$   r%   r%   Ï  s"   € ÷ pñ p¤Dð p¬X´c­]ñ pr'   c                ó†   € \        V 4      p \        V R,          RR7      pVe   V# \        \        V R,          4      V R7      # )a©  Verified PID of the gateway owned by ``home`` (pid file + runtime lock first, then the runtime
status record), or None. Every reader of another home's gateway identity goes through this so
they all prove the same thing: the PID passes the start-time reuse guard, its live command line is
a gateway's belonging to ``home``, and the record is not ``stopped``. Bare PID existence is not
identity -- a stale record whose PID was recycled by an unrelated process lent it ``served_profiles``
and put phantom gateways into the update inventory (#109680) -- while a launch-service gateway whose
``gateway.pid`` was unlinked is still live (#110166). Never unlinks ``home``'s identity files.rþ   F©rz  r   r€  )r   rm  ro  r  )rè   rD  s   & r$   Úlive_gateway_pid_for_homer„  Ï  sD   € ô �‹:€Dô ! ¨Õ!5ÀUÔ
K€CØ
‚Øˆ
Ü)Ô*=¸dÐEYÕ>YÓ*ZÐjnÔoÐor'   c                ó   € V ^8„  d   QhRR/# rh   ri   )r"   s   "r$   r%   r%   à  s   € ÷ 	#ñ 	#˜ñ 	#r'   c                 óJ  € \         P                  ! \        4      ;_uu_ 4        \        4       p \	        \        V 4      4      pVe&   V\        P                  ! 4       8w  d    RRR4       R# V P                  RR7       \        4        RRR4       R#   + '       g   i     R# ; i)z–Remove the PID file only if it belongs to this process: during --replace the old process's
atexit can fire AFTER the new process wrote its own record.NTrM  )
rð   rñ   rÂ   rÿ   r`  rƒ   r¾   r"  rO  ro  )r:   Úfile_pids     r$   Úremove_pid_filerˆ  à  sn   € ô 
×	Ò	œY×	'Õ	'Ü‹ˆÜ#¤O°DÓ$9Ó:ˆØÒ H´·	²	³Ô$;Ø÷	 
(Ñ	'ð
 	�‰˜tˆÔ$Ü Ô"÷ 
(×	'×	'Ò	'ús   £>BÁ+BÂB"	c                ó0   € V ^8„  d   QhR\         R\        /# r�  rÚ  )r"   s   "r$   r%   r%   ì  s   € ÷ ñ œSð ¤Tñ r'   c                óf  € \         P                  ! \        4      ;_uu_ 4        \        RV  R24      P	                  RR7      P                  4        F@  pVP                  R4      '       g   K  VP                  4       ^,          R9   u uuRRR4       # 	  RRR4       R#   + '       g   i     R# ; i)	zHTrue for a stopped / tracing-stop state (T/t) in ``/proc/<pid>/status``.r„  z/statusr°   r¦   zState:NF>   ÚTr«  )rð   rñ   r.  r   r¶   r·   r¿  r†  )rD  rÃ   s   & r$   Ú_process_is_stoppedrŒ  ì  s„   € ä	×	Ò	œW×	%Õ	%Ü˜6 #  gÐ.Ó/×9Ñ9À7Ð9ÓK×VÑVÖXˆDØ�‰˜x×(Ô(Ø—z‘z“| A•¨*Ñ4Ñ4÷ 
&Ò	%ÙX÷ 
&ñ ÷	 
&Ö	%ñ ús   £ABÁ-BÂBÂB0	c                óÚ   € V ^8„  d   QhR\         R\         R\        \        \         \        3,          ,          R\        \
        \        \        \         \        3,          ,          3,          /# )r   r|  rs  Úmetadatar<   )r!   r   r    r   rq  rP   )r"   s   "r$   r%   r%   õ  sP   € ÷ ñ ÜðÜðÜ)1´$´s¼C°xµ.Õ)Aðä
Œ4”œ$œs¤C˜x�.Õ)Ð)Õ*ñr'   c                ó´   € \        W4      p \        W0W4      p\        TP                  4       T#   \         d   p\        TP                  T4      ThRp?ii ; i)a‚  Acquire a machine-local lock keyed by scope + identity (one Telegram token across homes).

``metadata={"owner_kind": "process"}`` allows a non-gateway owner such as
a setup process. Its PID/start-time identity still gates stale recovery.
Raises :class:`gateway.status_lock_dir.ScopedLockDirUnusable` (logged once per dir with the repair) when this token may
not use the lock dir at all.N)r  Ú_acquire_scoped_lock_atrˆ  r   r²   r   )r|  rs  rŽ  rW  Úacquiredrs   s   &&&   r$   Úacquire_scoped_lockr’  õ  s^   € ô % UÓ5€Ið@Ü*¨9¸XÓPˆô   	× 0Ñ 0Ô1Ø€Oøô ô @Ü 	× 0Ñ 0°#Ó6¸CÐ?ûð@ús   �0 °A»AÁAc                óæ   € V ^8„  d   QhR\         R\        R\        R\        \        \        \        3,          ,          R\
        \        \        \        \        \        3,          ,          3,          /# )r   rW  r|  rs  rŽ  r<   )r   r!   r   r    r   rq  rP   )r"   s   "r$   r%   r%     sX   € ÷ 1ñ 1Üð1Üð1Ü+.ð1Ü:BÄ4ÌÌSÈÅ>Õ:Rð1ä
Œ4”œ$œs¤C˜x�.Õ)Ð)Õ*ñ1r'   c           
      ó  € ^ RI Hp \        V P                  RRR7       \        P
                  ! \        4      ;_uu_ 4        \        V R4      ;_uu_ 4         RRR4       RRR4       / \        4       CRTR\        V4      RT;'       g    / R	\        4       /Cp\        \        4       4      pV'       d   WeR
&   \        V 4      pVf"   V P                  4       '       d   \        V 4       V'       dµ   \!        V4      pV\"        P$                  ! 4       8X  d   \'        W4       RV3# V! Wx4      '       g   RV3# \        P
                  ! \(        4      ;_uu_ 4        V P+                  V P,                  R,           4      p	\"        P.                  ! W	4       \        V	4       RRR4        \1        W4       R#   + '       g   i     ELc; i  + '       g   i     ELo; i  + '       g   i     LF; i  \2         d    R\        T 4      3u # i ; i)rg  )Ú_scoped_lock_record_is_staleTr¢   ÚrbNr|  Úidentity_hashrŽ  r<  rú   Fz.stale)TN)Úgateway.status_scoped_locksr•  r   r²   rð   rñ   rY  r¶  r#  rz  r  rõ   rÌ   rƒ   rµ   rP  r`  r¾   r"  rk   r.  r  rB   r¿   rÃ  ÚFileExistsError)
rW  r|  rs  rŽ  r•  rß   rú   r…   Úexisting_pidÚ	tombstones
   &&&&      r$   r�  r�    s�  € õ Iä�)×"Ñ"¨D¸4Õ@ô 
×	Ò	Ô.×	/Õ	/´°iÀ×1FÕ1FØ÷ 2G×	/ðÜ
Ó
ðØ&¨¨ÄÈHÓ@UØ�H—N�N  L´,³.ñ€Fô &Ô&>Ó&@ÓA€GßØ#ˆyÑÜ˜yÓ)€HØÒ˜I×,Ñ,×.Ò.ä˜	Ô"ßÜ'¨Ó1ˆð œ2Ÿ9š9›;Ô&Ü˜YÔ/Ø˜�>Ð!Ù+¨H×CÒCØ˜(�?Ð"ô × Ò ¤×)Õ)Ø!×+Ñ+¨I¯N©N¸XÕ,EÓFˆIÜ�JŠJ�yÔ,Ü˜IÔ&÷ *ð1Ü˜Ô+ð Ð÷S 2G×1FÐ1Fú×	/×	/Ð	/ú÷B *×)ûô ô 1Ø”o iÓ0Ð0Ò0ð1úsC   ÁGÁF2	ÁGÅAGÆ%G- Æ2GÆ=	GÇG	ÇG*	Ç-HÈHz.gateway-takeover.jsonz.gateway-planned-stop.jsonc                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r   rá   r<   r  )r"   s   "r$   r%   r%   J  s   € ÷ ,ñ ,¬8´D­>ð ,ÄTñ ,r'   c                óV   € \        T ;'       g    \        4       4      pV\        ,          # )zVTakeover marker path; ``hermes_home`` is given only for a verified cross-home handoff.)rÔ   rÌ   Ú_TAKEOVER_MARKER_FILENAME)rá   rè   s   & r$   Ú_get_takeover_marker_pathrŸ  J  s$   € ä! +×"KÐ"KÔ1IÓ1KÓL€DØÔ+Õ+Ð+r'   c                ó$   € V ^8„  d   QhR\         /# r‡   r   )r"   s   "r$   r%   r%   P  s   € ÷ Fñ F¤tñ Fr'   c                  ó,   € \        4       \        ,          # ru   )rÌ   Ú_PLANNED_STOP_MARKER_FILENAMEri   r'   r$   Ú_get_planned_stop_marker_pathr£  P  s   € Ü#Ó%Ô(EÕEÐEr'   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   Ú
written_atr  r<   )r!   r=   rP   )r"   s   "r$   r%   r%   T  s!   € ÷ ñ ¤ð ¬Sð ´Tñ r'   c                 óÄ   €  \         P                  ! \        4      \         P                  ! V 4      ,
          pVP	                  4       V8„  #   \
        \        3 d     R # i ; irc  )r   r³   r   r(  r  rQ  rº   )r¥  r  Úages   && r$   r  r  T  sP   € ðÜ�lŠlœ3Ó¤(×"8Ò"8¸Ó"DÕDˆØ× Ñ Ó" UÑ*Ð*øÜ”zÐ"ô Úðús   ‚AA
 Á
AÁAc          
      ó    € V ^8„  d   QhR\         R\        R\        \        \        \
        \        3,          \        \        3,          ,          /# )r   r:   r  r<   )r   r=   r   rq  r    r!   r   )r"   s   "r$   r%   r%   \  s<   € ÷ ?ñ ?¤ð ?¬Sð ?´X¼eÄDÌÌcÈÅNÔTWÔY\ÐD\Õ>]Õ5^ñ ?r'   c                ó,  € \        V 4      pV'       g   R# \        VR4      pVe,   \        VP                  R4      ;'       g    RV4      '       d3   VP                  R4      RJg   \	        4       '       g   \        V 4       R# W#VP                  R4      3# )a©  ``(record, target_pid, target_start_time)`` for a usable marker, else None. Malformed/expired
markers can never match anyone, so they are unlinked here (must not wedge a new instance) --
except a request stamped ``accepted`` (``update_pause_record.mark_stop_accepted``): expired, it
matches nobody, but it can be the only trace that a still-draining gateway accepted an update's
stop, so it stays until that pause is settled.NÚ
target_pidr¥  r  ÚacceptedTÚtarget_start_time)rƒ   r`  r  râ   Ú_update_pause_on_diskrP  )r:   r  rß   rª  s   &&  r$   Ú_read_live_pid_markerr®  \  s~   € ô ˜TÓ"€FßÙÜ! &¨,Ó7€JØÒÔ-¨f¯j©j¸Ó.F×.LÐ.LÈ"Èe×TÒTØ�:‰:�jÓ!¨Ó-Ô5J×5LÒ5LÜ˜DÔ!ÙØ˜vŸz™zÐ*=Ó>Ð>Ð>r'   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   rª  r¬  r<   )r=   r   rP   )r"   s   "r$   r%   r%   m  s&   € ÷ 	^ñ 	^¤sð 	^¼sð 	^Ätñ 	^r'   c                ót   € V \         P                  ! 4       8w  d   R# \        V 4      pRW39   ;'       g    W8H  # )a¼  PID match with an optional start-time PID-reuse guard (watcher probe + consume). Both start
times known -> must match; either unknown -> PID equality decides (bounded by the marker TTL):
``_get_process_start_time`` is None without /proc (macOS, native Windows -- where the
planned-stop watcher matters most) and requiring a match there would misclassify a legitimate
``hermes gateway stop`` as an unexpected exit revived by the service manager.FN)r¾   r"  rO  )rª  r¬  Úour_start_times   && r$   Ú_pid_marker_names_selfr²  m  s:   € ð ”R—Y’Y“[Ô ÙÜ,¨ZÓ8€NØÐ%Ð6Ñ6×]Ð]Ð:KÑ:]Ð]r'   Ú
on_consumeÚkeepc                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r   r:   r  r´  r<   )r   r=   rP   )r"   s   "r$   r%   r%   y  s*   € ÷ ñ ¤tð ´sð ÔSWð Ôdhñ r'   c                óx  € \        W4      pVf   R# Vw  rVp\        4       pVP                  R4      p	V	e+   \        V	\        4      '       d   \        W˜4      '       g   R# M(VP                  R4      p
V
e   \        W¨4      '       g   R# \        Wg4      pV'       d   Ve	   V! W4       V'       g   \        V 4       V# )NFÚtarget_hermes_homeÚreplacer_hermes_home)r®  rÌ   râ   r„   r!   rÜ   r²  rP  )r:   r  r³  r´  r0  rß   rª  r¬  Úour_homeÚtarget_homeÚreplacer_homeÚmatchess   &$$$        r$   Ú_consume_pid_marker_for_selfr½  y  s®   € Ü" 4Ó/€FØ‚~ÙØ,2Ñ)€FÐ)ô
 (Ó)€HØ—*‘*Ð1Ó2€KØÒÜ˜+¤s×+Ò+Ô3DÀ[×3[Ò3[Ùð 4\ð Ÿ
™
Ð#9Ó:ˆØÒ$Ô->¸}×-WÒ-WÙÜ$ ZÓC€Gß�:Ò)Ù�4Ô ßÜ˜ÔØ€Nr'   rº  r¬  c                ó^   € V ^8„  d   QhR\         R\        \        ,          R\        R\        /# )r   rª  rº  r¬  r<   )r=   r   r   r   rP   )r"   s   "r$   r%   r%   “  s0   € ÷ ñ ÜðÜ%-¬d¥^ðÜORðä	ñr'   c               óJ  €  \        T;'       g    \        4       4      pV\        J d   \        V 4      p\	        \        V4      RV RVR\        V4      R\        P                  ! 4       R\        \        \        4       4      4      R\        4       /4      #   \         d     R# i ; i)ao  Record that ``target_pid`` is being replaced by this process; True on success. Captures the
target's ``start_time`` (PID-reuse guard) + a timestamp for TTL. A verified cross-home handoff
passes ``target_home`` + validated ``target_start_time`` so the marker lands in the target's
home; such callers must fail closed on False (the target's supervisor could revive it).rª  r¬  r·  Úreplacer_pidr¸  r¥  F)rÔ   rÌ   rÑ  rO  Ú_write_markerrŸ  r!   r¾   r"  r  r.  )rª  rº  r¬  Úmarker_homes   &$$ r$   Úwrite_takeover_markerrÃ  “  s™   € ðÜ,¨[×-VÐ-VÔ<TÓ<VÓWˆØ¤Ó&Ü 7¸
Ó CÐÜÔ6°{ÓCØ˜*Ð&9Ð;LØ ¤# kÓ"2°NÄBÇIÂIÃKØ"¤CÔ(>Ô?WÓ?YÓ(ZÓ$[Øœ,›.ð	F
ó ð 	øô ô Úðús   ‚B �BB ÂB"Â!B"c                ó^   € V ^8„  d   QhR\         R\        \        \        3,          R\        /# )r   r:   rß   r<   )r   r    r!   r   rP   )r"   s   "r$   r%   r%   ¨  s)   € ÷ ñ œð ¤d¬3´¨8¥nð ¼ñ r'   c                óB   €  \        W4       R#   \         d     R# i ; i)zDAtomically write a marker record; False (never raise) on OS failure.TF)rk   r.  )r:   rß   s   &&r$   rÁ  rÁ  ¨  s$   € ðÜ˜Ô&ÙøÜô Úðús   ‚ ��c                ó$   € V ^8„  d   QhR\         /# r‡   r  )r"   s   "r$   r%   r%   ±  s   € ÷ cñ c¬$ñ cr'   c                 ó4   € \        \        4       \        R7      # )zXConsume the takeover marker; True => planned takeover (exit 0); unlinked on match/stale.)r  )r½  rŸ  Ú_TAKEOVER_MARKER_TTL_Sri   r'   r$   Ú consume_takeover_marker_for_selfrÉ  ±  s   € ä'Ô(AÓ(CÔKaÔbÐbr'   c                ó>   € V ^8„  d   QhR\         \        ,          RR/# )r   rº  r<   Nr  )r"   s   "r$   r%   r%   ¶  s   € ÷ <ñ <¤x´¥~ð <Àñ <r'   c                ó.   € \        \        V 4      4       R# )zDRemove the takeover marker unconditionally. Safe to call repeatedly.N)rP  rŸ  )rº  s   &r$   Úclear_takeover_markerrÌ  ¶  s   € äÔ-¨kÓ:Ö;r'   c                ó”   € V ^8„  d   QhR\         \        \        3,          R\        \        \
        \
        \        3,          ,          /# r÷   )r    r!   r   r   rq  r=   r   )r"   s   "r$   r%   r%   »  s6   € ÷ !4ñ !4´´c¼3°hµð !4ÄHÌUÔSVÔX[Ô]aÐSaÕMbÕDcñ !4r'   c                ó¦  € \        V \        4      '       d   \        V 4      '       g   R# \        V 4      pV P	                  R4      pV P	                  R4      pVe§   V^ 8:  g    V\
        P                  ! 4       8X  g†   \        V\        4      '       dp   \        V\        4      '       gZ   \        V\        4      '       dD   VP                  4       '       d.   \        V4      P                  4       P                  4       '       g   R# \        V4      p\        W4      R8w  d   R# \!        V4      pVe   \#        V4      '       g   R# \%        VR,          4      ;'       g    / pVP	                  R4      p\        V4      '       dN   \        V4      V8w  g>   VP	                  R4      V8w  g(   \        V\        4      '       d   \'        Wt4      '       g   R# WV3# )a  Resolve a live scoped-lock owner to a verified ``(pid, start_time, home)``. A lock file is
only a claim: the record, the target home's PID record, and the live process must agree on
PID, start-time, gateway identity, and home. Missing legacy metadata fails closed.Nr!  rá   Úsamerþ   )r„   r    ræ  r`  râ   r¾   r"  r=   rP   r!   r¸   r   rÑ   Úis_absoluterÔ   Ú_scoped_lock_owner_staterŸ  rØ  rƒ   rÜ   )rß   Ú	owner_pidÚowner_start_timeÚraw_homerº  r  Ú
pid_recordÚpid_record_homes   &       r$   Ú$_validated_scoped_lock_gateway_ownerr×  »  sa  € ô �fœd×#Ò#Ô+EÀf×+MÒ+MÙÜ  Ó(€IØ—z‘z ,Ó/ÐØ�z‰z˜-Ó(€HàÒ˜Y¨!œ^¨y¼B¿IºI»KÔ/GÜÐ*¬C×0Ò0´JÐ?OÔQU×4VÒ4VÜ˜(¤C×(Ò(°·±×0@Ò0@Ü�H‹~×(Ñ(Ó*×6Ñ6×8Ò8áÜ(¨Ó2€KÜ 	Ó<ÀÔFÙÜ(¨Ó3€LØÒÔ(OÐP\×(]Ò(]Ùä  ¨}Õ!<Ó=×CÐCÀ€JØ —n‘n ]Ó3€Oä& z×2Ò2Ü˜JÓ'¨9Ô4Ø�>‰>˜,Ó'Ð+;Ô;Ü˜/¬3×/Ò/Ü  ×>Ò>áØ¨Ð3Ð3r'   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   rÒ  rÓ  r<   )r=   r!   )r"   s   "r$   r%   r%   ß  s&   € ÷ Gñ G¬ð G¼sð GÄsñ Gr'   c                ó^   € \        V 4      '       g   R# \        V 4      pVf   R# W!8X  d   R# R# )zBReturn ``same``, ``exited``, or ``unknown`` for a validated owner.Úexitedr;  rÏ  )rh  rO  )rÒ  rÓ  Úlive_start_times   && r$   rÑ  rÑ  ß  s3   € ä�y×!Ò!ÙÜ-¨iÓ8€OàÒÙØ$Ô8ˆ6ÐF¸hÐFr'   c                óv   € V ^8„  d   QhR\         R\         R\         R\        R\        \        \        3,          /# )r   rÒ  rÓ  ÚattemptsÚdelayr<   )r=   rO   rq  rP   )r"   s   "r$   r%   r%   ê  sD   € ÷ Rñ RÜðRÜ&)ðRÜ8;ðRÜDIðRä
Œ4”ˆ:ÕñRr'   c               óÜ   € \        \        ^ V4      4       FD  p\        W4      pVR8X  d   Ru # VR8X  d   Ru # \        P                  ! \        RV4      4       KF  	  R\        W4      R8H  3# )zFReturn ``(exited, safe_to_force)`` after bounded identity-aware waits.rÚ  Fr;  rR   rÏ  )TF)FF)r¾  rV   rÑ  rT   Úsleep)rÒ  rÓ  rÝ  rÞ  Ú_rZ   s   &&$$  r$   Ú _wait_for_scoped_lock_owner_exitrâ  ê  sj   € ô ”3�q˜(Ó#Ö$ˆÜ(¨ÓEˆØ�HÔØÒØ�IÔØÒÜ�
Š
”3�s˜E“?Ö#ñ %ð Ô*¨9ÓGÈ6ÑQÐQÐQr'   c                ó0   € V ^8„  d   QhR\         R\        /# r�  )r=   rå  )r"   s   "r$   r%   r%   ø  s   € ÷ ñ ¤Cð ¬Dñ r'   c                óÒ   € \         '       d   . #  ^ RIpVP                  \        V 4      4      P	                  RR7      #   \
         d    \        P                  RT RR7       . u # i ; i)zÝBest-effort snapshot of ``pid``'s live descendants (POSIX only; never raises). Take it while
the parent is alive -- once it exits the children are reparented and undiscoverable. ``[]`` on
Windows (taskkill /T tree-kills).NT)Ú	recursivez-Could not snapshot children of gateway PID %d©Úexc_info)rN  r‰  rŒ  r=   ÚchildrenrÂ   rn   rq   )rD  r‰  s   & r$   Ú_snapshot_gateway_childrenré  ø  s_   € ÷ ƒ{Øˆ	ðÛØ�~‰~œc #›hÓ'×0Ñ0¸4Ð0Ó@Ð@øÜô Ü�‰ÐDÀcÐTXˆÔYØŠ	ðús   �-> ¾%A&Á%A&rN   r±   c                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r   rè  Ú
parent_pidrN   r<   )rå  r=   rO   )r"   s   "r$   r%   r%     s)   € ÷ ,ñ ,¤Dð ,¼ð ,Äuð ,ÔWZñ ,r'   c          
     ó¸  € \         '       g	   V '       g   ^ # ^ p ^ RIp. pV  F”  p VP                  4       '       d    VP                  4       VP                  8X  d   K;  VP                  4       V8X  d$   \        P                  RVP                  V4       Ks  VP                  4        VP                  V4       K–  	  V'       g   ^ # VP                  V\        RV4      R	7      w  rx\!        V4      pV F  p VP#                  4        V^,          pK  	  V'       d   \        P%                  RW14       V#   TP                   d     EK$  \         d*    \        P                  R\        TRR4      TRR7        EKV  i ; i  \         d)    \        P                  R
\        TRR4      TRR7        K¾  i ; i  \         d    \        P                  RTRR7        T# i ; i)aØ  Best-effort reap of a dead gateway's orphaned descendants (POSIX; surviving adapter
subprocesses keep holding token locks); returns count signalled. Call only AFTER the parent is
confirmed dead, with a :func:`_snapshot_gateway_children` snapshot. ``is_running()`` is
identity-aware so a recycled child PID is never signalled; a child whose ppid still equals
``parent_pid`` is skipped (parent alive => not an orphan). SIGTERM, bounded wait, SIGKILL
survivors. Never raises.NzCSkipping child PID %d of old gateway %d: parent still appears alivez2Could not terminate child PID %s of old gateway %drD  Ú?Træ  rR   rS   z3Could not force-kill child PID %s of old gateway %dz@Reaped %d orphaned child process(es) of replaced gateway PID %d.z-Child reap for replaced gateway PID %d failed)rN  r‰  Ú
is_runningr:  r–  Úppidrn   rq   rD  Ú	terminater¹   r•  rÂ   rU  Ú
wait_procsrV   rÀ   rR  ro   )	rè  rë  rN   Úreapedr‰  ÚliveÚchildÚgonert  s	   &$$      r$   Úreap_gateway_childrenrö    s¸  € ÷ ƒ{Ÿ(ÙØ€Fð!aÛØˆÛˆEðTØ×'Ñ'×)Ò)¨U¯\©\«^¸v×?SÑ?SÔ-SÙØ—:‘:“< :Ô-Ü—L‘Lð ")Ø*/¯)©)°ZôAáØ—‘Ô!Ø—‘˜EÖ"ñ ÷ ÙØ×'Ñ'¨´c¸#¸wÓ6GÐ'ÓH‰ˆÜ�T“ˆÛˆEðTØ—
‘
”Ø˜!•’ñ ÷ Ü�K‰KÐZØô,ð €Møð+ ×'Ñ'ô ÛÜô TÜ—‘ÐQÜ$ U¨E°3Ó7¸Èdð ÷ Tð TðTûô ô TÜ—‘ÐRÜ$ U¨E°3Ó7¸Èdð ÷ TðTûô ô aÜ�‰ÐDÀjÐ[_ˆÕ`Ø€MðaúsŽ   šF2 ¦5D1ÁF2 Á6D1ÂF2 Â!D1Â6F2 Ã/F2 Ã4E<ÄF2 ÄF2 Ä1E9ÅF2 ÅE9Å%E9Å4F2 Å8E9Å9F2 Å</F/Æ+F2 Æ.F/Æ/F2 Æ2#GÇGÚgraceful_attemptsÚforce_attemptsc          	      ó€   € V ^8„  d   QhR\         \        \        3,          R\        R\        R\        \        ,          /# )r   rß   r÷  rø  r<   )r    r!   r   r=   r   )r"   s   "r$   r%   r%   5  s8   € ÷ ñ Ü””c��NðÜ25ðÜLOðäŒc…]ñr'   c               óæ   € \        V 4      pVf   R# Vw  rEp\        V4      p\        WFVR7      '       g   R#  \        WEVVR7      p\	        V4       Ve   \        WtR7       V#   \	        T4       i ; i)av  Terminate one verified scoped-lock holder for explicit ``--replace``. Returns the owner PID
only after that exact PID/start-time identity exited; validation or marker-write failure returns
None without signalling (a cross-home handoff must place a consumable marker in the target's
home or its supervisor revives it: flap loop). On POSIX the snapshotted children are reaped.N)rº  r¬  )r÷  rø  )rë  )r×  ré  rÃ  Ú_terminate_verified_ownerrÌ  rö  )	rß   r÷  rø  r  rÒ  rÓ  rº  Úowner_childrenÚreplaceds	   &$$      r$   Útake_over_scoped_lock_holderrþ  5  sƒ   € ô 1°Ó8€EØ‚}ÙØ/4Ñ,€I ä/°	Ó:€NÜ ØÐ>N÷ó ñ ð+Ü,ØÐ;LØ)ô
ˆô 	˜kÔ*ØÒÜ˜nÕCØ€Oøô 	˜kÕ*ús   ¸A# Á#A0c                ój   € V ^8„  d   QhR\         R\         R\         R\         R\        \         ,          /# )r   rÒ  rÓ  r÷  rø  r<   r‚  )r"   s   "r$   r%   r%   S  s8   € ÷ ñ ÜðÜ&)ðÜADðÜVYðäŒc…]ñr'   c               ó   € \        W4      pVR8X  d   V # VR8w  d   R# VRRR/3VRRRR	V/33 F9  w  rVp \        V 3/ VB  \	        YYVR
7      w  r‰T'       d   T u # T	'       d   K8   R# 	  R#   \         d    T u u # \         d      R# i ; i)z¹Bounded identity-aware SIGTERM-then-SIGKILL of a verified owner; the PID once it exited, else
None. Per signal step: ``ProcessLookupError`` => already gone; other ``OSError`` => refuse.rÚ  rÏ  Ng      à?rA  Fg      Ð?TrB  )rÝ  rÞ  )rÑ  r`  ÚProcessLookupErrorr.  râ  )
rÒ  rÓ  r÷  rø  rZ   rÝ  rÞ  rf  rÚ  Úsafe_to_forces
   &&$$      r$   rû  rû  S  s¼   € ô
 % YÓA€EØ�ÔØÐØ�„Ùà	˜C '¨5Ð!1Ð2Ø	˜ ¨Ð/DÐFVÐWÐXó$Ñˆ˜ð	Ü˜)Ñ. vÒ.ô
 !AØ°(ô!
Ñˆ÷ ØÒß‰}Úñ!$ñ" øô "ô 	ØÔÜô 	Ûð	ús   µA-Á-BÁ>BÂBÂBc                ó0   € V ^8„  d   QhR\         R\        /# )r   rª  r<   rÚ  )r"   s   "r$   r%   r%   q  s   € ÷ ñ ¬#ð ´$ñ r'   c                ó‚   € \        \        4       RV R\        V 4      R\        P                  ! 4       R\        4       /4      # )zÂRecord that ``target_pid`` is being stopped intentionally: unexpected SIGTERM exits non-zero
so service managers revive the gateway; the CLI writes this first so a deliberate stop exits
cleanly.rª  r¬  Ústopper_pidr¥  )rÁ  r£  rO  r¾   r"  r  )rª  s   &r$   Úwrite_planned_stop_markerr  q  s=   € ô Ô6Ó8Ø�jÐ"5Ô7NÈzÓ7ZØ”r—y’y“{ L´,³.ð;ó ð r'   c                ó$   € V ^8„  d   QhR\         /# r‡   r  )r"   s   "r$   r%   r%   ~  s   € ÷ ñ œtñ r'   c                 ór  a€ ^ RI Hp  V P                  4       o \        P                  ! SP
                  4      ;_uu_ 4       p\        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      uuRRR4       #   + '       g   i     R# ; i  \         d     R# \         d     R# i ; i)ao  A Windows update pause of this checkout is on disk (its record or a recovery's claim), or the
record directory cannot be listed. Only then does a consume need the pause lock and a checkpoint,
and only then can accepted-stop evidence beside a request still be owed: with none, every pause
was settled by recovery or the updater (or never made: every non-Windows host).©Úupdate_pause_recordc              3   ó  <"  € T Fu  pVP                   SP                   8H  ;'       gP    VP                   P                  SP                   R ,           4      ;'       d    VP                   P                  R4      x € Kw  	  R# 5i)Ú.z.claimN)rB   r¿  r'  )r«   Úerß   s   & €r$   r­   Ú(_update_pause_on_disk.<locals>.<genexpr>‡  sd   øé € ð )Ù '˜1ð —v‘v §¡Ñ,×tÐt°·±×1BÑ1BÀ6Ç;Á;ÐQTÕCTÓ1U×1sÐ1sÐZ[×Z`ÑZ`×ZiÑZiÐjrÓZsÔtÛ 'ùs   ƒ$B ¨3B Á$B TFN)	Ú
hermes_clir
  Úrecord_pathr¾   Úscandirr²   r½  rY  r.  )r
  Úentriesrß   s     @r$   r­  r­  ~  s‡   ø€ õ
 /Ø ×,Ñ,Ó.€FðÜ�ZŠZ˜Ÿ™×&Ô&¨'ß“3ô )Ù 'ó)—3—3’3ô )Ù 'ó)ó )÷ '×&×&Ó&ûô ô ÚÜô ÚðúsA   ™(B Á BÁ$BÁ;
B ÂB	ÂB ÂB ÂB6Â(B6Â1B6Â5B6c                óV   € V ^8„  d   QhR\         R\        \        \        3,          RR/# rÆ  r�   )r"   s   "r$   r%   r%   �  s.   € ÷ Añ A¤4ð A´´c¼3°hµð AÀDñ Ar'   c                óÌ   € ^ RI Hp \        4       '       d:   VP                  \        4      ;_uu_ 4        VP                  W4       RRR4       R# R#   + '       g   i     R# ; i)z±``on_consume``, decided after the request was read: an update writes its record before its
request, so a pause that appeared since the consumer first looked is checkpointed too.r	  N)r  r
  r­  Ú_mutexÚ_PLANNED_STOP_MUTEX_WAIT_SÚmark_stop_consumed)r:   rß   r
  s   && r$   Ú_checkpoint_planned_stopr  �  sH   € õ /Ü×ÒØ ×'Ñ'Ô(B×CÕCØ×2Ñ2°4Ô@÷ DÑCñ ßC×CÐCús   ´AÁA#	c                ó$   € V ^8„  d   QhR\         /# r‡   r  )r"   s   "r$   r%   r%   ˜  s   € ÷ jñ j¬dñ jr'   c                 ó   € ^ RI Hp  \        4       p \        4       pV'       g   \	        V P                  V4      4       V'       d   V P                  \        4      M\        P                  ! 4       ;_uu_ 4        \        V\        \        R7      uuRRR4       #   + '       g   i     R# ; i  \         dF   p\        P                  RT4       \        \        4       \        RT P                   R7      u Rp?# Rp?ii ; i)zDReturn True when the current process is being intentionally stopped.r	  )r  r³  NzDPlanned-stop checkpoint skipped (%s); the stop request stays on diskT)r  r´  r³  )r  r
  r£  r­  rP  Ú_accepted_pathr  r  rð   Únullcontextr½  Ú_PLANNED_STOP_MARKER_TTL_Sr  r.  rn   rp   Úmark_stop_accepted)r
  r:   Úpausedrs   s       r$   Ú$consume_planned_stop_marker_for_selfr   ˜  sÄ   € å.Ü(Ó*€DðjÜ&Ó(ˆßÜÐ/×>Ñ>¸tÓDÔE÷ HNÐ ×'Ñ'Ô(BÔCÔS]×SiÒSiÓSk×kÑkÜ/°Ô<VÜ;SôU÷ l×k×kÓkûô ô jô 	�‰Ð]Ð_bÔcÜ+Ô,IÓ,KÔSmØ15ÐBU×BhÑBhôjõ 	jûðjúsA   ’3B- Á2B- Á8BÂ
B- ÂB*	Â$B- Â*B- Â-C=Â8:C8Ã2C=Ã8C=c                ó$   € V ^8„  d   QhR\         /# r‡   r  )r"   s   "r$   r%   r%   ®  s   € ÷ Oñ O¬$ñ Or'   c                 ó~   € \        \        4       \        4      p V RJ;'       d    \        V ^,          V ^,          4      # )züNon-destructive watcher probe: True when a live planned-stop marker names us. Never unlinks a
matching marker (the shutdown handler does the authoritative consume); malformed/expired ones
are still cleaned up; markers naming another PID are left alone.N)r®  r£  r  r²  )r0  s    r$   Ú planned_stop_marker_targets_selfr#  ®  s8   € ô #Ô#@Ó#BÔD^Ó_€FØ˜Ð×NÐNÔ"8¸À½ÀFÈ1ÅIÓ"NÐNr'   rz  c                óh   € V ^8„  d   QhR\         \        ,          R\        R\         \        ,          /# )r   r  rz  r<   )r   r   rP   r=   )r"   s   "r$   r%   r%   ¶  s,   € ÷ 5ñ 5Ü”t�nð5Ü7;ð5äŒc…]ñ5r'   c               ó\  € T ;'       g    \        4       p\        V4      p\        V4      '       dÂ   \        V4      \	        V4      3pV e   V P
                  MRpRpRpV Fe  p\        V4      p	V	f   K  Vf   \        V4      M\        W…R7      '       * p
V
'       d   \        W‰VR7      '       d   V	u # V
'       g   Ve   RpKc  RpKg  	  V'       g   \        W!V'       * R7       V f   \        4       # R# V f   \        4       MRpVe   V\        P                  ! 4       8X  d   \        W!R7       V# )u#  PID of a running gateway (lock + PID file verified against the live process), or None.
An explicit ``pid_path`` is a scoped query into that home's identity files: records are
validated against the probed home (not the serve process's) (#106406). While the runtime lock
is HELD, a live SAME-home record the identity matcher rejects is never cleanup-unlinked, scoped
or not: the holder is a gateway whatever its command line reads as, and unlinking a held
``gateway.lock`` leaves it locking a deleted inode so the next starter double-runs (#125610,
#123109). Unscoped, a live ``gateway.pid`` that truthfully names ANOTHER home's gateway is
poison inside this home and is unlinked on refusal â€” the held lock stays (#89315). Dead
records and inactive-lock metadata still take the full poison-file cleanup.NFr€  T)rz  rx  rƒ  )rÿ   r  r¸  rT  rZ  r²   ri  r2  rå   r  r}  ro  r¾   r"  )r  rz  Úresolved_pid_pathr·  ÚrecordsrÝ   Úsaw_live_pidÚforeign_live_pidrß   rD  Úhome_okrx  s   &$          r$   rn  rn  ¶  s/  € ð !×3Ð3¤M£OÐÜ/Ð0AÓBÐÜ%Ð&8×9Ò9äÐ.Ó/Ô1JÐK]Ó1^ð
ˆð ,4Ò+?˜ŸšÀTˆØˆØ ÐÛˆFÜ'¨Ó/ˆCØŠ{ÙàBOÒBWÔ6°vÔ>Ü8¸Ô]Ô]ð ÷ Ô;Ø¨=÷ó ð ’
÷
 ˜-Ò3Ø#’à#'Ò ñ' ÷( Ü%Ø!ÐP`ÔL`õð 4<Ò3CÔ-Ó/ÐMÈÐMð
 7?Ò6FÔ0Ô2ÈD€KØÒ˜k¬R¯YªY«[Ô8Ü!Ð"3ÕQØÐr'   c                óh   € V ^8„  d   QhR\         R\        \        \        \        3,          ,          /# r  )r   r   rq  r=   rO   )r"   s   "r$   r%   r%   î  s(   € ÷ 0"ñ 0"¬dð 0"´xÄÄcÌ5ÀjÕ@QÕ7Rñ 0"r'   c                ó„  a€ \        V 4      p\        V4      p\        VR4      p\        VR4      '       g   R# \        V4      '       g   R# \	        V4      pV'       d   \        V4      V3MV3p\        V4      '       g   \        R4      h\        V^ ,          4      oSeV   S^ 8:  gO   \        ;QJ d&    V3R lVR,           4       F  '       g   K   RM	  RM! V3R lVR,           4       4      '       d   \        R	4      h\        S4      '       g   \        R
4      h\        S4      p\        ;QJ d    . R V 4       F  NK  	  5M! R V 4       4      pVe;   \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        R4      h \        V.VO5!  '       g   \        R4      h \        ;QJ d    T3R lT 4       F  '       d   K   RM	  RM! T3R lT 4       4      '       g   \        R4      h\!        T4      p	\"        '       g   ST	3#  ^ RIp
\!        T
P'                  S4      P)                  4       4      p\-        T^d,          4      \/        T	4      8w  d   \        R4      hST3#   \        \        3 d   p\        R4      ThRp?ii ; i  \*         d   p\        R4      ThRp?ii ; i)zFReturn a verified process identity or fail on ambiguous runtime state.zgateway PIDzgateway lockNz)gateway PID or lock metadata is malformedc              3   ó@   <"  € T F  p\        V4      S8g  x € K  	  R # 5iru   )r`  ©r«   rß   rD  s   & €r$   r­   Ú2get_running_pid_identity_strict.<locals>.<genexpr>  s   øé € Ð%`ÑT_È&Ô&6°vÓ&>À#Ö&EÓT_ùs   ƒ:r?   NNTFz(gateway PID and lock identities disagreezgateway identity is not livec              3   óB   "  € T F  qP                  R 4      x € K  	  R# 5i)r!  N)râ   )r«   rß   s   & r$   r­   r/    s   é € ÐB¹'°—:‘:˜l×+Ð+»'ùs   ‚c              3   ó(   "  € T F  qR J x € K
  	  R # 5iru   ri   )r«   rH   s   & r$   r­   r/    s   é € Ð#F¹v°e¨T¥M»vùs   ‚z$gateway creation time is unavailablez gateway process identity changedz"gateway creation time is malformedc              3   ó<   <"  € T F  p\        VS4      x € K  	  R # 5iru   )r  r.  s   & €r$   r­   r/    s   øé € ÐSÉ7ÀÔ/°¸×<Ð<Ë7ùs   ƒz1runtime metadata does not identify a live gatewayz*exact gateway creation time is unavailable)r   r  r½  rÀ  rZ  rT  rl  r¼  r`  r½  rh  rO  rq  rP  rQ  rº   rO   rN  r‰  rŒ  Úcreate_timerÂ   r‹  r=   )r  r&  r·  r—  Úlock_recordr'  rc  Ústartsrs   rb  r‰  Úexact_create_timerD  s   &           @r$   Úget_running_pid_identity_strictr7  î  sW  ø€ ä˜X›ÐÜ/Ð0AÓBÐÜ$Ð%6¸ÓF€Jô Ð1°>×BÒBÙÜ1Ð2D×EÒEÙÜ+Ð,>Ó?€K÷
 EOÔÐ 1Ó2°KÑ@ÐU`ÐTb€GÜˆw�<Š<ÜÐFÓGÐGÜ
˜7 1�:Ó
&€CØ
‚{�c˜Q”h§#£#Ô%`ÐT[Ð\^ÖT_Ó%`§#§#¢#Ô%`ÐT[Ð\^ÖT_Ó%`×"`Ò"`ÜÐEÓFÐFÜ�s×ÒÜÐ9Ó:Ð:Ü+¨CÓ0€MßŒUÑB¹'ÓB�U‰UÑB¹'ÓBÓB€FØÒ§£Ñ#F¹vÓ#F§§¢Ñ#F¹vÓ#F× FÒ FÜÐAÓBÐBðJÜ! -Ð9°&×9Ò9ÜÐAÓBÐBð :÷ ‹3ÔSÉ7ÓS�3�3Š3ÔSÉ7ÓS×SÒSÜÐNÓOÐOÜ�MÓ"€Gß‹;Ø�Gˆ|ÐðRÛä! &§.¡.°Ó"5×"AÑ"AÓ"CÓDÐô Ð Õ$Ó%¬¨W«Ô5ÜÐ=Ó>Ð>ØÐ!Ð!Ð!øô# ”zÐ"ô JÜÐ?Ó@ÀcÐIûðJûô ô RÜÐGÓHÈcÐQûðRús0   ÆI> È#,J# É>J ÊJÊJ Ê#J?Ê.J:Ê:J?Úttl_secondsc          	      ót   € V ^8„  d   QhR\         \        ,          R\        R\        R\         \        ,          /# )r   r  rz  r8  r<   )r   r   rP   rO   r=   )r"   s   "r$   r%   r%   !  s6   € ÷ ñ Ü”t�nðÜ7;ðäðô Œc…]ñr'   c               óZ  € V^ 8:  d   \        WR7      # T ;'       g    \        4       pV RJ pV\        V4      .pV'       d   VP                  \	        4       4       \
        ;QJ d    . R V 4       F  NK  	  5M! R V 4       4      p\        V4      \        V4      V3p\        P                  ! 4       p\        ;_uu_ 4        \        P                  V4      p	V	e6   W‰^ ,          ,
          V8:  d"   V	^,          V8X  d   V	^,          uuRRR4       # RRR4       \        WR7      p
\
        ;QJ d    . R V 4       F  NK  	  5M! R V 4       4      p\        ;_uu_ 4        \        P                  ! 4       Wº3\        V&   RRR4       V
#   + '       g   i     L; i  + '       g   i     T
# ; i)zµCached ``get_running_pid()`` for dashboard polling: short TTL, invalidated on PID/lock/
runtime-status file changes, so status endpoints do not re-flock ``gateway.lock`` constantly.rƒ  Nc              3   ó8   "  € T F  p\        V4      x € K  	  R # 5iru   ©rw  ©r«   Úps   & r$   r­   Ú)get_running_pid_cached.<locals>.<genexpr>/  s   é € Ð@¹°1Ô+¨A×.Ð.»ùr¯   c              3   ó8   "  € T F  p\        V4      x € K  	  R # 5iru   r<  r=  s   & r$   r­   r?  7  s   é € ÐJÁ'¸QÔ 5°a× 8Ð 8Ã'ùr¯   )rn  rÿ   r  r¹   r  rq  r!   rP   rT   rU   rl  rm  râ   )r  rz  r8  r&  Úinclude_runtime_statusÚwatchedÚ	signaturer\  r³   ÚcachedrD  Úrefreshed_signatures   &$$         r$   rm  rm  !  sI  € ð �aÔÜ˜xÔEÐEØ ×3Ð3¤M£OÐØ%¨Ð-Ðà Ô"8Ð9JÓ"KÐL€GßØ�‰Ô/Ó1Ô2ß”Ñ@¹Ó@—‘Ñ@¹Ó@Ó@€IÜÐ Ó!¤4¨Ó#6Ð8NÐ
O€CÜ
�.Š.Ó
€Cß	(Ö	(Ü+×/Ñ/°Ó4ˆØÒ #¨q­	¥/°[Ô"@ÀVÈAÅYÐR[ÔE[Ø˜!•9÷ 
)×	(Ò	(ô ˜(Ô
@€Cßœ%ÑJÁ'ÓJŸ%™%ÑJÁ'ÓJÓJÐß	(Ö	(Ü+/¯>ª>Ó+;Ð=PÐ*VÔ" 3Ñ'÷ 
)à€J÷ 
)×	(ú÷ 
)Ö	(à€Jús   Ã AFÅFÆF	ÆF*	c                ó¬  € V ^8„  d   Qh/ ^ \         9   dR   \        \        \        \        \        3,          \        \
        \        \        \        ,          3,          3,          ;R&   ^\         9   d   \        \        ,          ;R&   ^\         9   d&   \        \        \        \        3,          ,          ;R&   ^\         9   d   \        \        ,          ;R&   # )r   rm  rý  rþ  rŠ   )Ú__conditional_annotations__r    rq  r!   rP   rO   r   r=   r   r   r   )r"   s   "r$   r%   r%      s    € ÷ Bñ B÷h bÒ aœD¤¤s¬D´$ Õ!7¼¼uÄeÌXÔVYÍ]Ð?ZÕ9[Ð![Õ\Ñ añiB÷z 2Ò 1œH¤T�NÑ 1ñ{B÷| 7Ò 6”x¤¤S¬# X¥Õ/Ñ 6ñ}B÷R >Ò =œÔ!5Õ6Ñ =òSBr'   i   rv   )é   g      ^@ru   r�  )ÌrG  r|   r“   rð   rC   rv  rB  Úloggingr)  r¾   r  rº  rS  rW  r  r*   rT   Údataclassesr   r   r   r   Úpathlibr   Útypingr   r	   r
   r   Úhermes_dir_aclr   Úgateway.status_inline_sourcer   r   r   rî   r   r   r   rV  r   Úgateway.status_lock_dirr   r   Úutilsr   rÜ  r†  rŠ  rä  r  r  rN  ÚobjectrÑ  r  Ú_gateway_lock_handler…  Ú&_GATEWAY_RUNNING_PID_CACHE_TTL_SECONDSÚLockrl  rm  Ú	getLoggerrx   rn   r   ÚRLockr‰   rý  rþ  rl   rŠ   r‹   r�   r•   r—   rÉ   rÌ   rÔ   rÜ   rå   Úcompilerì   rõ   rû   rÿ   r  r  r  r  r+  r2  Ú	frozensetr>  r@  r`  rP  ÚSTART_TIME_DRIFT_TOLERANCErq  rz  r  rO  r‘  rŸ  rÈ  rÎ  rÔ  rØ  rÜ  ræ  rì  ró  rù  rÿ  r  r  r  r  r  r#  r-  r2  r=  rƒ   rk   rP  rT  rZ  r`  re  ri  ro  rw  r}  r‘  rh  rž  r¦  r«  r¯  r³  r¸  r½  rÀ  rÄ  rÃ  rÔ  rÚ  r  r  r  r  r  Ú_RUNTIME_STATUS_STALE_TTL_Sr  r  r"  r  r/  r,  r+  r2  r  rG  rT  rY  r}  ro  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  r­  r  r   r#  rn  r7  rm  r%   )rG  s   @r$   Ú<module>r[     s–  øð÷Bó Û Û Û Û Û Û Û 	Û 	Û Û Û Û 
Û Û Ý !ß ,Ñ ,Ý ß 6Ó 6Ý (÷ñ ÷
 iÑ hÝ ;ß RÝ #à‡<�<�7ÔÜãà €Ø+Ð Ø €Ø�l‰l˜gÑ%€Ù	‹€Ø'Ð ØÐ ñ #Ð Ø),Ð &Ø"+§.¢.Ó"2Ð à_aÐ Ó aà	×	Ò	˜8Ó	$€÷`Tñ `TðF 'Ÿ_š_Ó.Ð Ø-1Ð Ó 1Ø26Ð Ó 6õNð :>Ð Ó =õ&÷Eð E÷Sð Sô�
ô ò ØLQ÷ ð  õF%õ9õ
JðØOS÷ð& —J’JÐ<Ó=Ð õõ"	]õ6÷Kð Kõ=õ2õ&)ð
 #Ð õñ: "Ð#;Ð=PÐ"QÓRÐ õð,'CØ$ð'CØMQ÷'CõTZð !Ð ð Qk÷ :õEõEõ õF(õ
õ:DõNõD9õ
FõFõYõQõ
	ð  ŸZšZÐ(_Ó`Ð õõeõjõ.hð"bØIM÷bõ"õ õõ$Yõð:°u÷ :õ0Iõ%÷
Jð J÷Tð T÷ð õ[õ
õ+õ
.ð)Ø@D÷)õõ "õD8õõõ>õ	÷$ð $õSõQõõõIõZð
E/Ø"ðE/Ø7=ðE/ØX^ðE/àðE/à4:ðE/àLRðE/àjpðE/ð ðE/ð 4:ðE/ð SYðE/ð !ð	E/ð :@ð	E/ð W]ð	E/ð
 "ðE/ð
 GMðE/ð #ðE/ð ðE/ð 5;ðE/ð ]bðE/ð -1ðE/ð ðE/ð 9>÷E/õPBð9Ø$ð9ØFJ÷9õ(
÷?ð ?ð "Ð ð 4O÷cõaõ5õ
ñ & y°*Ð&=Ó>Ð õ2õPñ
 �$Ô÷-ð -ó ð-õ õ"$NõNõ4Ið(NØ%)ðNØ:@ðNàRVðNð ðNð QUðNð IMð	Nð
 AE÷NòbØQU÷ð õ6põ"	#õ÷ð õ$1ðz 5Ð ØÐ Ø <Ð ØÐ ÷,ò ,÷F÷÷?÷"	^ñÀtñ ÐZ_÷ ñ ñ4Ø6:ñØU[÷ñ ÷*÷c÷
<ò <÷
!4÷HG÷R÷ñ,És÷ ,ñ ,ñ^Ø8:ñØRT÷ñ ÷<÷<ð !Ð ÷÷"A÷j÷,Oó5Ø>B÷5ò 5÷p0"ófØ>Bñà?÷ô r'   