+
    jHàj¤s ã                   ó€  € R t ^ RIt^ RIt^ RIt^ RIHt ^ RIt^ RIt^ RIt^ RI	t
^ RIHtHt ^ RIHt ^ RIHt ^ RIHt ^ RIHt ]P,                  ! R4      t]t]! 0 R˜m4      tR	R
R.3RR
.33t. R™OtR R ltR R ltRRRR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# R$ llt&]! 0 R›m4      t']'R%0,
          t(R& R' lt)R( R) lt*R*Rœ/R+ R, llt+R�t,R- R. lt-R/ R0 lt.R1 R2 lt/R3 R4 lt0R5RR6R/R7 R8 llt1R5RR6R/R9 R: llt2R;R</R= R> llt3R? R@ lt4RšRA lt5RB RC lt6RD RE lt7RF RG lt8RH RI lt9RJ RK lt:RL RM lt;RN RO lt<RP RQ lt=RRR/RS RT llt>RU RV lt?RWRžRXR</RY RZ llt@R[ R\ ltAR] R^ ltBR_ R` ltCRa Rb ltDRc Rd ltEReRfRgR/Rh Ri lltFRjR<RgR/Rk Rl lltGRm tHRntIRotJRptKRqtLRrR/Rs Rt lltMRu Rv ltNRgR/Rw Rx lltORy Rz ltPR{ R| ltQR} R~ ltRR R€ ltSRgR/R� R‚ lltTRšRƒ ltUR„ R… lt7] ! R† R‡4      4       tVRˆ R‰ ltWRŠ R‹ ltXRŒ R� ltYRŽ R� ltZR� R‘ lt[R’ R“ lt\R” R• lt]RŸR– R— llt^R# ) a@  Gateway fleet restart + post-update verification for ``hermes update``.

Split out of ``hermes_cli/update_cmd.py``; every name is re-imported there so
``hermes_cli.update_cmd.<name>`` keeps resolving/monkeypatching. Origin helpers are
imported lazily inside each function (no import cycle; test patches stay effective).
N)Úsuppress)Ú	dataclassÚfield©ÚPath)Ú_best_effort)ÚPROFILE_MARKER_NAME©Ú _gateway_service_matches_profilezhermes_cli.update_cmdÚuserÚ	systemctlz--userÚsystemc                ó(   € V ^8„  d   QhR\         RR/# )é   ÚokÚreturnN©Úbool)Úformats   "Ú@/home/ubuntu/.hermes/hermes-agent/hermes_cli/update_cmd_fleet.pyÚ__annotate__r   )   s   € ÷ 8ñ 8¬ð 8°ñ 8ó    c                 óô   € ^ RI Hp ^ RIHp ^ RIHp T ;'       g    V! 4       p V! 4       R,          p\        \        4      ;_uu_ 4        T! Y@'       d   RMR4       RRR4       R#   + '       g   i     R# ; i)é    ©Úget_hermes_home)Úcommitted_success)Údurable_write_bytesz.update_exit_codeó   0ó   1N)Úhermes_cli.update_cmdr   Úhermes_cli.update_receiptr   Úpm.filesystemr   r   ÚOSError)r   r   r   r   Úpaths   &    r   Ú_write_gateway_update_exit_coder%   )   sT   € Ý5Ý;Ý1ð 
×	"Ð	"Ñ Ó"€BÙÓÐ2Õ2€DÜ	”'×	Õ	á˜D®"¡$°$Ô7÷ 
×	×	Ò	ús   Á	A&Á&A7	c                ó$   € V ^8„  d   QhR\         /# ©r   r   r   )r   s   "r   r   r   7   s   € ÷ ;ñ ;¬Dñ ;r   c                 ó2   € ^ RI Hp  V ! 4       \        ,          # )ud  LEGACY per-``HERMES_HOME`` breadcrumb. Read-compat only â€” nothing writes it any more.

One host runs one multiplexing gateway, so the pullâ†’restart obligation is host-scoped
(``hermes_cli/update_host_obligation.py``). An obligation armed by the old per-profile code
is still read and cleared here so an in-flight update is discharged after the upgrade.
r   )r    r   Ú_FLEET_RESTART_PENDING_NAMEr   s    r   Ú"_fleet_restart_pending_marker_pathr*   7   s   € õ 6ÙÓÔ:Õ:Ð:r   Úexpected_shaÚ ÚruntimesÚownerc                ól   € V ^8„  d   QhR\         R\        \        ,          R,          R\         R\        /# )r   r+   r-   Nr.   r   )ÚstrÚlistÚdictr   )r   s   "r   r   r   B   s;   € ÷ Mñ M¼ð MÌTÔRVÍZÐZ^ÕM^ð MÔnqð MÔ{ñ Mr   c                óî   € V. 8X  d   R# ^ RI Hp ^ RIHp V! 4       P	                  \        4       P                  4      '       d   \        P                  R4       R# V! \        4       W\        4       VR7      # )u€  Arm the HOST pullâ†’restart obligation. Never raises; False when no store every profile reads took it.

An unwritable host state dir falls back to this profile's per-home marker, which settles the
debt only on an install proven to have no other profile; otherwise the arm returns False and
the commit point refuses to move (``update_host_obligation.arm_host_obligation``, review S2).
T©Ú_m)Úarm_host_obligationzFSkipping fleet-restart-pending obligation under pytest (live checkout))r+   r-   Úprofiler.   )
r    r5   Ú!hermes_cli.update_host_obligationr6   Ú_pytest_owns_live_checkoutr*   ÚparentÚloggerÚdebugÚ_current_profile_name)r+   r-   r.   r5   r6   s   $$$  r   Ú#_write_fleet_restart_pending_markerr>   B   sc   € ð �2„~ñ Ý(ÝEÙ	ƒt×&Ñ&Ô'IÓ'K×'RÑ'R×SÒSÜ�‰Ð]Ô^ÙÙÔAÓCÐR^Ü'<Ó'>ÀeôMð Mr   c                ó$   € V ^8„  d   QhR\         /# r'   ©r0   )r   s   "r   r   r   W   s   € ÷ ñ œsñ r   c                 óV   €  ^ RI Hp  V ! 4       ;'       g    R#   \         d     R# i ; i)uX   Profile whose CLI armed the obligation (diagnostics only â€” the record is host-scoped).©Úget_active_profile_nameÚdefaultr,   )Úhermes_cli.profilesrC   Ú	ExceptionrB   s    r   r=   r=   W   s-   € ðÝ?Ù&Ó(×5Ð5¨IÐ5øÜô Úðús   ‚ – ™(§(c                ó   € V ^8„  d   QhRR/# ©r   r   N© )r   s   "r   r   r   `   s   € ÷ añ a¨Tñ ar   c                 ól   € ^ RI Hp  ^ RIHp V! 4        V ! 4       P	                  \        4       RR7       R# )z\Discharge the obligation for the whole host (legacy per-home marker included). Never raises.r4   )Úclear_host_obligationzfleet-restart-pending)ÚlabelN)r    r5   r8   rK   Ú_clear_marker_filer*   )r5   rK   s     r   Ú#_clear_fleet_restart_pending_markerrN   `   s(   € å(ÝGÙÔÙƒD×ÑÔ>Ó@ÐH_ÐÖ`r   c                ó$   € V ^8„  d   QhR\         /# r'   r   )r   s   "r   r   r   h   s   € ÷ ñ ¬ñ r   c                 óÈ   € ^ RI Hp  V ! 4       '       d   R# \        \        4      ;_uu_ 4        \	        4       P                  4       uuRRR4       #   + '       g   i     R# ; i)uD   True when this HOST owes a fleet restart â€” from any profile's CLI.©Úhost_obligation_presentTNF)r8   rR   r   r#   r*   Úis_filerQ   s    r   Ú_fleet_restart_obligation_armedrT   h   s=   € åIÙ× Ò ÙÜ	”'×	Õ	Ü1Ó3×;Ñ;Ó=÷ 
×	×	Ñ	áús   ­AÁA!	c                óT   € V ^8„  d   QhR\         \        \        3,          R,          /# rH   ©r2   r0   )r   s   "r   r   r   r   s    € ÷ ñ œD¤¤c �N¨TÕ1ñ r   c                 ó8  € ^ RI Hp Hp V! 4       pVe   V# V ! 4       '       d   R#  \        4       P	                  RR7      p/ pTP                  4        F,  pTP                  R4      w  rgpT'       d   Yd9   d    R# Y„T&   K.  	  T#   \
        \        3 d     R# i ; i)z³Armed obligation as ``key=value`` fields: HOST record first, then the legacy marker.

``None`` means nothing armed OR a malformed record; both must leave the obligation standing.
)rR   Úobligation_fieldsNú	utf-8-sig©ÚencodingÚ=)	r8   rR   rX   r*   Ú	read_textr#   ÚUnicodeErrorÚ
splitlinesÚ	partition)	rR   rX   ÚfieldsÚtextÚlegacyÚlineÚkeyÚsepÚvalues	            r   Ú_obligation_fieldsrh   r   sŸ   € ÷
 ]ÙÓ €FØÒØˆÙ× Ò ñ ðÜ1Ó3×=Ñ=À{Ð=ÓSˆð  €FØ—‘Ö!ˆØŸ.™.¨Ó-‰ˆ�%ß�c”mÚØˆs‹ñ	 "ð
 €Møô ”\Ð"ô Úðús   ¦B ÂBÂBc                ó2   € V ^8„  d   QhR\         R,          /# rH   r@   )r   s   "r   r   r   Œ   s   € ÷ =ñ =œs T�zñ =r   c                 óâ   € ^ RI Hp Hp  ^ RIHp V! RR7      ;'       g    / P                  R4      pV'       d   \        V4      # R#   \         d    T ! R.T! 4       P                  4      u # i ; i)z@Current on-disk checkout HEAD, or None if it cannot be resolved.)Ú_capture_head_shar5   )Úget_code_identityT)ÚrefreshÚshaNÚgit)	r    rk   r5   Úhermes_cli.version_inforl   Úgetr0   rF   ÚPROJECT_ROOT)rk   r5   rl   rn   s       r   Ú_current_checkout_shars   Œ   sa   € ç;ð=Ý=Ù ¨Ô.×4Ð4°"×9Ñ9¸%Ó@ˆßŒs�3‹xÐ( DÐ(øÜô =Ù  % ©"«$×*;Ñ*;Ó<Ò<ð=ús!   ŠA  A º
A ÁA Á$A.Á-A.c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úreceiptr   )r2   r   )r   s   "r   r   r   —   s   € ÷ >ñ >¤tð >´ñ >r   c                ó\  € V P                  R4      pV P                  R4      pVR9  g   VR	9   d   R# V P                  R4      p\        V\        4      '       d   VP                  R4      '       d   R# V^ 8H  ;'       g    VR8H  p\        V P                  R4      4      ;'       d    V'       * # )
ak  True when *receipt* is from an update that did not finish cleanly.

The command boundary stamps a ``stop_reason`` on every receipt, including clean
ones (``completed at command boundary``, ``sys.exit(0)``); it must not make a
successful receipt look unfinished, or the next ``hermes update`` retriggers
``fleet_restart_pending`` from pre-pull plan SHAs (#98022).
Ú	exit_codeÚoutcomeTÚgateway_restartÚ
incompleteÚsuccessÚstop_reason)r   N)ÚfailedÚpartialÚrunning)rq   Ú
isinstancer2   r   )ru   rw   rx   ry   Ú	succeededs   &    r   Ú_receipt_looks_unfinishedr‚   —   s˜   € ð —‘˜KÓ(€IØ�k‰k˜)Ó$€GØ˜	Ô! WÐ0PÔ%PÙØ—k‘kÐ"3Ó4€OÜ�/¤4×(Ò(¨_×-@Ñ-@À×-NÒ-NÙð ˜Q‘×6Ð6 '¨YÑ"6€IÜ�—‘˜MÓ*Ó+×=Ð=°I´Ð=r   c                óJ   € V ^8„  d   QhR\         R\        R,          R\        /# )r   ru   r+   Nr   )r2   r0   r   )r   s   "r   r   r   ¬   s&   € ÷ &ñ &¬Dð &ÄÀdÅ
ð &ÔVZñ &r   c                ó¾  aaa€ ^ RI Hp \        V \        4      '       g   R# S;'       g    V! 4       oS'       g   R# R V3R llo^ RIHo V P                  R4      p\        V\        4      '       dE   V'       d=   \        ;QJ d     VV3R lV 4       F  '       g   K   R# 	  R# ! VV3R lV 4       4      # \        V 4      '       g   R# V P                  R	4      p\        V\        4      '       g   R# \        ;QJ d8    V3R
 lVP                  R4      ;'       g    .  4       F  '       g   K   R# 	  R# ! V3R
 lVP                  R4      ;'       g    .  4       4      # )a6  True when ``update_receipts/latest.json`` records a runtime SHA skew.

Prefer the post-restart ``fleet`` matrix. ``plan.runtimes[].code_sha`` is captured
*before* the pull, so a finished update's plan always looks stale and must not
retrigger a restart; consult it only for an unfinished receipt.

See #95294.
©rs   Fc                ó$   € V ^8„  d   QhR\         /# r'   r   )r   s   "r   r   Ú4_receipt_reports_stale_runtime.<locals>.__annotate__¼   s   € ÷ Eñ E¤4ñ Er   c                 óX   <€ \        V 4      ;'       d    \        V 4      \        S4      8g  # ©N)r   r0   )Úcode_shar+   s   &€r   Ú_sha_mismatchÚ5_receipt_reports_stale_runtime.<locals>._sha_mismatch¼   s#   ø€ Ü�H‹~×DÐD¤# h£-´3°|Ó3DÑ"DÐDr   )Úrow_is_externalÚfleetc              3   óä   <"  € T Fe  p\        V\        4      ;'       dI    S! V4      '       * ;'       d4    VP                  R 4      R8H  ;'       g    S! VP                  R4      4      x € Kg  	  R# 5i)ÚstateÚstalerŠ   N©r€   r2   rq   )Ú.0Úentryr‹   r�   s   & €€r   Ú	<genexpr>Ú1_receipt_reports_stale_runtime.<locals>.<genexpr>Ã   ss   øé € ð 
ñ �ô �uœdÓ#÷ Xð XÙ# EÓ*Ô*÷Xð Xà—‘˜7Ó# wÑ.×VÐV±-ÀÇ	Á	È*Ó@UÓ2VôXó ùs   ƒA0ŸA0´A0Á A0TÚplanc              3   ó‚   <"  € T F4  p\        V\        4      ;'       d    S! VP                  R 4      4      x € K6  	  R# 5i)rŠ   Nr’   )r“   Úruntimer‹   s   & €r   r•   r–   Ï   s8   øé € ð á1ˆGô 	�7œDÓ!×LÐL¡m°G·K±KÀ
Ó4KÓ&LÔLÛ1ùs   ƒ?Ÿ ?r-   )
r    rs   r€   r2   r!   r�   rq   r1   Úanyr‚   )ru   r+   rs   rŽ   r—   r‹   r�   s   &f   @@r   Ú_receipt_reports_stale_runtimer›   ¬   s-  ú€ õ <Ü�gœt×$Ò$ÙØ×:Ð:Ñ#8Ó#:€LßÙ÷Eð Eõ :à�K‰K˜Ó €EÜ�%œ×Ò§5ß‹sõ 
ñ ó	
�sŒsð 	
Šsð 	
ˆsõ 
ñ ó	
ó 
ð 	
ô % W×-Ò-ÙØ�;‰;�vÓ€DÜ�dœD×!Ò!Ùß‹3ô à—x‘x 
Ó+×1Ð1¨rÐ1ó�3Œ3ð Š3ð ˆ3ô à—x‘x 
Ó+×1Ð1¨rÐ1óó ð r   úmanual-servec          	      ó˜   € V ^8„  d   QhR\         R\        \         ,          R\        \        \        \        3,          ,          R,          /# )r   ru   Úpending_manualr   N)r2   r1   ÚsetÚtupler0   )r   s   "r   r   r   à   s;   € ÷ (ñ (¤Dð (¼$¼t½*ð (ÌÌUÔSVÔX[ÐS[Í_ÕI]Ð`dÕIdñ (r   c                ó(  € V P                  R4      ;'       g    / pVP                  R4      ;'       g    .  Uu. uF  q3R3NK  	  ppTP                  R V P                  R4      ;'       g    .  4       4       TP                  R V P                  R4      ;'       g    .  4       4       TP                  R V P                  R	4      ;'       g    .  4       4       \        4       pR
pV F—  w  r7\        V\        4      '       g   RpK  VP                  RV4      pVP                  R4      p	VR9   d#   VP                  R4      \
        9   d	   W19  d   Kk  VR8w  g   V	'       d   V	R8X  d   RpK…  VP                  W‰34       K™  	  V'       d   R# T# u upi )a
  Pure coverage classification after manual retention of this receipt snapshot.

Empty means this receipt owes no gateways, not that an independent marker owes none. Unknown identities, unclassified serve backends and failed manual transfers make coverage unverified.
r—   r-   Nc              3   ó(   "  € T F  qR 3x € K
  	  R # 5ir‰   rI   ©r“   r”   s   & r   r•   Ú)_receipt_owed_gateways.<locals>.<genexpr>ç   ó   é € ÐYÑ.X U˜4•=Ó.Xùó   ‚Úpending_manual_servesc              3   ó(   "  € T F  qR 3x € K
  	  R # 5ir‰   rI   r£   s   & r   r•   r¤   è   r¥   r¦   Úcarried_manual_servesc              3   ó(   "  € T F  qR 3x € K
  	  R# 5i©ÚgatewayNrI   r£   s   & r   r•   r¤   é   s   é € ÐNÑ3M¨%˜9Õ%Ó3Mùr¦   rŽ   FTÚkindr7   Ú
supervisorr¬   Úunknown©ÚserveÚ	dashboard)rq   ÚextendrŸ   r€   r2   Ú_SUPERVISED_SERVE_BACKENDSÚadd)
ru   rž   r—   r”   ÚentriesÚowedÚ
unverifiedÚdefault_kindr­   r7   s
   &&        r   Ú_receipt_owed_gatewaysrº   à   so  € ð
 �;‰;�vÓ×$Ð$ "€DØKOÏ8É8ÐT^ÓK_×KeÐKeÐceÐKeÓ/fÑKeÀ%¸³ÑKe€GÐ/fØ‡N�NÑY¨g¯k©kÐ:QÓ.R×.XÐ.XÐVXÐ.XÓYÔYØ‡N�NÑY¨g¯k©kÐ:QÓ.R×.XÐ.XÐVXÐ.XÓYÔYØ‡N�NÑN°7·;±;¸wÓ3G×3MÐ3MÈ2Ð3MÓNÔNÜ!$£€DØ€JÛ&ÑˆÜ˜%¤×&Ò&ØˆJÙØ�y‰y˜ Ó.ˆØ—)‘)˜IÓ&ˆð Ð)Ô)¨e¯i©i¸Ó.EÔIcÔ.cÐhmô  iDÙØ�9Ô§G¨w¸)Ô/CØˆJÙØ�‰�$�Ö!ñ#  '÷$ ˆ4Ð' 4Ð'ùò1 0gs   ¹Fc                óv   € V ^8„  d   QhR\         R\        \        \        \        3,          ,          R,          /# )r   rŽ   r   N)r1   rŸ   r    r0   )r   s   "r   r   r     s,   € ÷ ñ ¤4ð ¬C´´c¼3°hµÕ,@À4Õ,Gñ r   c                ó*  € \        4       pV  F‚  p\        V\        4      '       d   VP                  R4      MRpV'       d   VR8X  d    R# VP	                  RV34       TP                  R VP                  R4      ;'       g    .  4       4       K„  	  V# )a  ``(kind, profile)`` identities the live rows vouch for; ``None`` when any row is unidentified.

A multiplexer's row carries the ``served_profiles`` its runtime status records (``_fleet_row``
keeps the field only when well-formed), so one live process covers every profile it serves.
r7   Nr¯   r¬   c              3   ó*   "  € T F	  pR V3x € K  	  R# 5ir«   rI   )r“   Úserveds   & r   r•   Ú*_fleet_covered_gateways.<locals>.<genexpr>  s   é € ÐZÑ9Y¨v˜	 6Õ*Ó9Yùs   ‚Úserved_profiles)rŸ   r€   r2   rq   rµ   Úupdate)rŽ   ÚcoveredÚrowr7   s   &   r   Ú_fleet_covered_gatewaysrÄ     s~   € ô %(£E€GÛˆÜ(2°3¼×(=Ò(=�#—'‘'˜)Ô$À4ˆß˜' YÔ.ÚØ�‰�Y Ð(Ô)Ø�‰ÑZ¸¿¹ÐARÓ9S×9YÐ9YÐWYÐ9YÓZÖZñ ð €Nr   Úaccept_statesc          
      ó¨   € V ^8„  d   QhR\         R,          R\        R\        \        \         \         3,          ,          R,          R\        R\        /# )r   r+   Nru   r·   rÅ   r   )r0   r2   rŸ   r    r   )r   s   "r   r   r     sU   € ÷ ñ ¬S°4­Zð Ä$ð ÌcÔRWÔX[Ô]`ÐX`ÕRaÕNbÐeiÕNið ô  ~Cð ô  W[ñ r   c               óî  a aa€ S '       g   R# ^ RI HpHo  Vf   R# V'       g4   \        VP	                  R4      ;'       g    / P	                  R4      4      # V! 4       pV'       dE   \
        ;QJ d!    VV V3R lV 4       F  '       g   K   RM	  RM! VV V3R lV 4       4      '       d   R# \        V4      pVRJ;'       d    W&8*  #   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)	zHRequire a successor at the expected SHA for every owed gateway identity.F©Úcollect_fleet_versionsr�   Nr—   r-   c              3   ó¤   <"  € T FE  pS! V4      '       d   K  VP                  R 4      S9  ;'       g    VP                  R4      S8g  x € KG  	  R# 5i)r�   rŠ   N)rq   )r“   rÃ   rÅ   r+   r�   s   & €€€r   r•   Ú-_live_fleet_covers_receipt.<locals>.<genexpr>  sI   øé € ð 
á�¡O°C×$8ô YˆC�G‰G�GÓ MÑ1×XÐX°S·W±W¸ZÓ5HÈLÑ5XÔXÛùs   ƒA˜A³ATz0Could not reconcile pending fleet identities: %s)
r!   rÉ   r�   r   rq   rš   rÄ   rF   r;   r<   )	r+   ru   r·   rÅ   rÉ   rŽ   rÂ   Úexcr�   s	   f&&d    @r   Ú_live_fleet_covers_receiptrÍ     sÂ   ú€ çÙßQðØŠ<ÙßÜ˜Ÿ™ VÓ,×2Ð2°×7Ñ7¸
ÓCÓDÐDÙ&Ó(ˆçŸ›ö 
áó
ŸŸšö 
áó
÷ 
ò 
ñ Ü)¨%Ó0ˆØ˜dÐ"×6Ð6 t¡Ð6øÜô Ü�‰ÐGÈÔMÝûðúsK   —C �C ¥C ÁC ÁC Á'
C Á2C ÂC Â-C ÃC ÃC4ÃC/Ã/C4c                óv   € V ^8„  d   QhR\         R\        \        \        \        3,          ,          R,          /# )r   Ú	inventoryr   N)ÚobjectrŸ   r    r0   )r   s   "r   r   r   /  s,   € ÷ ñ ¤Vð ´´E¼#¼s¸(µOÕ0DÀtÕ0Kñ r   c                óð  € ^ RI Hp V f   R# \        V \        4      '       d   V P	                  R4      ^8w  d   \        R4      hV P	                  R4      p\        V\        4      '       g   \        R4      h\        4       pV Fð  p\        V\        4      '       g   \        R4      hV! V4      '       d   K4  VP	                  R4      R	8X  d/   VP	                  R
4      '       d   VP                  \        4       Kx  VP	                  R4      pVP	                  R4      R	8w  g4   \        V\        4      '       d   VP                  4       '       d   VR8X  d   \        R4      hVP                  R	V34       Kò  	  V# )z­The ``("gateway", profile)`` set a marker's inventory owes; None when it recorded none.

Raises ValueError for a malformed or unsupported inventory, which keeps the marker.
)Ú runtime_outside_gateway_evidenceNÚversionz#unsupported fleet-restart inventoryr-   z+fleet-restart inventory has no runtime listz,fleet-restart inventory row is not an objectr­   r¬   Ústopped_unmappedr7   r¯   z8fleet-restart inventory row is not an identified gateway)Ú'hermes_cli.update_cmd_fleet_gatewaylessrÒ   r€   r2   rq   Ú
ValueErrorr1   rŸ   rµ   Ú_UNMAPPED_GATEWAYr0   Ústrip)rÏ   rÒ   r-   r·   r™   r7   s   &     r   Ú_marker_owed_gatewaysrÙ   /  s0  € õ
 YàÒÙÜ�i¤×&Ò&¨)¯-©-¸	Ó*BÀaÔ*GÜÐ>Ó?Ð?Ø�}‰}˜ZÓ(€HÜ�h¤×%Ò%ÜÐFÓGÐGÜ!$£€DÛˆÜ˜'¤4×(Ò(ÜÐKÓLÐLÙ+¨G×4Ò4ÙØ�;‰;�vÓ )Ô+°·±Ð<N×0OÒ0OØ�H‰HÔ&Ô'ÙØ—+‘+˜iÓ(ˆØ�;‰;�vÓ )Ô+´:¸gÄs×3KÒ3KÐSZ×S`ÑS`×SbÒSbÐfmÐqzÔfzÜÐWÓXÐXØ�‰�)˜WÐ%Ö&ñ ð €Kr   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   Úcheckout_shar+   r   ©r0   r   )r   s   "r   r   r   M  s!   € ÷ ñ ´ð Ä3ð Ì4ñ r   c                ó&  € ^ RI Hp ^ RIHp  W8H  ;'       g    V! V4      ;'       d    V! 4       pT'       g   R# \        4        \
        P                  RT R,          4       R#   \         d"   p\
        P                  RT4        Rp?R# Rp?ii ; i)	zÅSettle an inventory-less marker on a host with no live gateway (#118742).

Only when the host itself shows nothing the update could still owe a restart to, and HEAD
still holds the code it pulled.
©Úcheckout_contains)Úhost_owes_no_gateway_restartzHGateway-less host probe failed; keeping fleet-restart-pending marker: %sNFzCFleet-restart-pending marker discharged: host runs no gateway at %sºNé
   NT)Ú$hermes_cli.update_cmd_fleet_checkoutrß   rÕ   rà   rF   r;   r<   rN   )rÛ   r+   rß   rà   ÚgatewaylessrÌ   s   &&    r   Ú_discharge_gatewayless_markerrå   M  s~   € õ GÝTðØ#Ñ3×VÐVÑ7HÈÓ7V×zÐzÑ\xÓ\zˆ÷ ÙÜ'Ô)Ü
‡L�LÐVÐXdÐehÕXiÔjÙøô ô Ü�‰Ð_ÐadÔeÝûðús!   Ž
A$ ™A$ ©A$ Á$BÁ/BÂBc                ó$   € V ^8„  d   QhR\         /# r'   r   )r   s   "r   r   r   b  s   € ÷ Vñ V¤tñ Vr   c                 óT  a€ ^ RI Hp   \        4       pVf   R# VP                  RR4      P	                  4       p\        \        P                  ! VP                  RR4      4      4      pTe*   T'       g"   \        4        \        P                  R4       R	# Te   T'       g   R# \        4       pTe   YB8w  d   T ! T4      '       g   R# TpT'       g   R#  ^ R
IHpHo T! 4       pT'       dI   T'       gZ   \&        ;QJ d    T3R lT 4       F  '       d   K   RM	  R	M! T3R lT 4       4      '       d   Tf	   T'       g   R# \)        YB4      # \+        T4      p	T	f   R# T FK  p
S! T
4      '       d   K  T
P                  R4      R8w  g"   \-        T
P                  R4      4      T8w  g   KJ   R# 	  Te   T\.        0,
          T	8:  g   R# T'       dX   \.        T9   dM   \+        T U
u. uF  p
S! T
4      '       d   K  T
NK  	  up
4      ;'       g    \1        4       T,
          '       g   R# \        4        \        P                  R\3        T4      TR,          4       R	#   \        \        \        3 d     R# i ; i  \$         d"   p\        P                  RT4        Rp?R# Rp?ii ; iu up
i )u!  Settle only the inventory stored with this marker's target SHA.

Historical receipts cannot narrow this obligation. Malformed or unsupported inventories stay
fail-closed; empty discovery never proves a stopped gateway recovered. Two shapes record no
obligation and settle without one: an explicit empty inventory (a pull that found no gateway,
#115311) clears outright, and an inventory-less marker (the pre-inventory writer, or a tail
that died before its inventory was recorded, #115638) clears once every live gateway is
current on the checkout â€” there is no recorded owed set, so the fleet running the code on disk
is the whole of the evidence the marker's warning can be about, even after HEAD moved past
``expected_sha`` by an out-of-band pull â€” and so does an inventory-less record armed with no
SHA at all (a no-op update whose head capture failed, #125952): with no owed set and no SHA,
the checkout is the only code it can be held to. With no live gateway at all, the inventory-less marker
asks the host instead (``update_cmd_fleet_gatewayless``): it clears when no profile left a
gateway that should be running and every live runtime is supervisor-owned or handed off, so a
Desktop-only install stops failing every later update (#118742).

A serve/dashboard row whose supervisor owns the restart (Desktop backend, systemd/launchd
unit, Windows service) is outside the gateway matrix's evidence, not evidence against it â€”
the same boundary ``_receipt_owed_gateways`` draws for receipts (#115090) and the restart
phase draws for the Desktop backend (#111494). Counting it made the warning permanently
undischargeable on every host that runs a dashboard. A manual-serve row still needs its
durable handoff (``defer_manual_serve``), and an unclassified backend stays fail-closed.
Discharging here strands nobody: the same row is still accounted at update time by
``update_inventory.report_unaccounted_runtimes``, which prints it and records an owed restart when the restart
phase never touched it â€” this marker only stops re-warning about it on every later startup.
rÞ   NFr+   r,   rÏ   ÚnullzGFleet-restart-pending marker discharged: no gateway obligation recordedTrÈ   z<Fleet probe failed; keeping fleet-restart-pending marker: %sc              3   ó4   <"  € T F  pS! V4      x € K  	  R # 5ir‰   rI   )r“   rÃ   r�   s   & €r   r•   Ú0_marker_only_restart_obsolete.<locals>.<genexpr>ž  s   øé € Ð-TÉeÀs©o¸c×.BÐ.BËeùs   ƒr�   ÚcurrentrŠ   zGFleet-restart-pending marker discharged: %d gateway(s) already serve %srá   )rã   rß   rh   rq   rØ   rÙ   ÚjsonÚloadsr#   r^   rÖ   rN   r;   r<   rs   r!   rÉ   r�   rF   Úallrå   rÄ   r0   r×   rŸ   Úlen)rß   ra   r+   r·   rÛ   Ú
target_sharÉ   rŽ   rÌ   rÂ   rÃ   r�   s              @r   Ú_marker_only_restart_obsoleterñ   b  s,  ø€ õ6 GðÜ#Ó%ˆØŠ>ÙØ—z‘z .°"Ó5×;Ñ;Ó=ˆÜ$¤T§Z¢Z°·
±
¸;ÈÓ0OÓ%PÓQˆð Ò§ô 	,Ô-Ü�‰Ð^Ô_ÙØÒ§ÙÜ(Ó*€LØÒ˜LÔ8ÑARÐS_×A`ÒA`Ùð €JßÙðßUÙ&Ó(ˆ÷ Ÿ¯#«#Ô-TÉeÓ-T¯#¯#ª#Ô-TÉeÓ-T×*TÒ*TØÒ§<ñ Ü,¨\ÓHÐHÜ% eÓ,€GØ‚ÙÛˆÙ˜3×ÒÙØ�7‰7�7Ó˜yÔ(¬C°·±¸
Ó0CÓ,DÈ
Ö,RÚñ	 ð
 Ò Ô(9Ð':Õ :¸gÔ EÙßÔ! TÔ)Ô3JÙ!Ó>™E�S©¸×)=�SˆS™EÑ>ó4@÷ 4Ið 4IÜCFÃ5ÈD÷3Qô 3Qñ Ü'Ô)Ü
‡L�LØQÜˆE‹
�J˜s•Oôñ øôg ”\¤:Ð.ô Úðûô, ô Ü�‰ÐSÐUXÔYÝûðüò( ?s;   ‰I ™AI ÃI6 Ç#J%Ç8J%ÉI3É2I3É6J"ÊJÊJ"c                ó>   € V ^8„  d   QhR\         R\        R,          /# )r   ru   r   NrV   )r   s   "r   r   r   »  s   € ÷ /ñ /¬dð /´s¸Tµzñ /r   c                óB  € V P                  R4      p\        V\        4      '       d	   V'       g   R# VP                  R4      '       g   VP                  R4      '       d   R# V P                  R4      ;'       g    / P                  R4      pV'       d   \        V4      # R# )zTReturn the pulled SHA when the restart phase completed, even if a later step failed.ry   Nrz   Úphase_errorÚpost_updatern   )rq   r€   r2   r0   )ru   ry   Úpost_shas   &  r   Ú _receipt_restart_phase_completedr÷   »  sy   € à—k‘kÐ"3Ó4€OÜ�o¤t×,Ò,·OÙØ×Ñ˜<×(Ò(¨O×,?Ñ,?À×,NÒ,NÙØ—‘˜MÓ*×0Ð0¨b×5Ñ5°eÓ<€Hß$Œ3ˆx‹=Ð.¨$Ð.r   ru   rž   c                ón   € V ^8„  d   QhR\         R,          R\        \         ,          R,          R\        /# ©r   ru   Nrž   r   ©r2   r1   r   )r   s   "r   r   r   Æ  s8   € ÷ Rñ R¬d°T­kð RÔRVÔW[ÕR\Ð_cÕRcð RÔosñ Rr   c                ó  € ^ RI Hp ^ RIHp ^ RIHp V f   V! 4       ;'       g    / p Vf	   V! V 4      p\        4       '       d   \        4       '       * # \        W4      p\        V 4      '       g   R# \        V! 4       W4      '       * # )zGRequire identity-matched gateways at checkout HEAD for update catch-up.r…   ©Úread_latest_receipt©Úretain_receipt_manual_servesF)r    rs   r!   rý   Ú#hermes_cli.update_serve_obligationsrÿ   rT   rñ   rº   r›   rÍ   )ru   rž   rs   rý   rÿ   r·   s   $$    r   Ú_pending_fleet_restart_neededr  Æ  sq   € å;Ý=ÝPà‚Ù%Ó'×-Ð-¨2ˆØÒÙ5°gÓ>ˆä&×(Ò(Ü0Ó2Ô2Ð2Ü! 'Ó:€DÜ)¨'×2Ò2ÙÜ)Ñ*?Ó*AÀ7ÓQÔQÐQr   c                ón   € V ^8„  d   QhR\         R,          R\        \         ,          R,          R\        /# rù   rú   )r   s   "r   r   r   Ù  s6   € ÷ Rñ R¬4°$­;ð RÌtÔTXÍzÐ\`ÕO`ð RÔlpñ Rr   c                ó`  € ^ RI Hp ^ RIHp ^ RIHp V f   V! 4       ;'       g    / p Vf	   V! V 4      p\        4       '       d   \        4       '       * # \        W4      p\        V 4      '       g   R# \        V 4      pV'       d   \        W`VRR7      '       d   R# \        V! 4       W4      '       * # )zJHold a completed restart to the code it pulled, not a later checkout HEAD.r…   rü   rþ   F)rÅ   )rë   r‘   )r    rs   r!   rý   r   rÿ   rT   rñ   rº   r›   r÷   rÍ   )ru   rž   rs   rý   rÿ   r·   Úrestarted_tos   $$     r   Ú_update_owes_fleet_restartr  Ù  s“   € å;Ý=ÝPà‚Ù%Ó'×-Ð-¨2ˆØÒÙ5°gÓ>ˆä&×(Ò(Ü0Ó2Ô2Ð2Ü! 'Ó:€DÜ)¨'×2Ò2ÙÜ3°GÓ<€L÷ Ô2°<È$Ð^r×sÓsÙÜ)Ñ*?Ó*AÀ7ÓQÔQÐQr   ÚstartupFc                ó(   € V ^8„  d   QhR\         RR/# )r   r  r   Nr   )r   s   "r   r   r   ñ  s   € ÷ Qñ Q¬Dð Q¸Tñ Qr   c                ó¸   € V '       d   \         P                  M\         P                  p\        RVR7       \        RVR7       V '       d   \        RVR7       R# R# )z<Print the specific interrupted-update fleet-restart warning.uT   âš  A previous `hermes update` pulled new code but did not restart running gateways.)ÚfilezG  Gateways may still be serving pre-update modules (mixed sys.modules).z2  Run `hermes update` or `hermes gateway restart`.N)ÚsysÚstderrÚstdoutÚprint)r  Ústreams   $ r   Ú_warn_pending_fleet_restartr  ñ  s>   € ç"ŒS�ZŠZ¬¯
©
€FÜ	Ð
`ÐgmÕnÜ	Ð
SÐZ`ÕaßÜÐBÈ×Pñ r   c                ó   € V ^8„  d   QhRR/# rH   rI   )r   s   "r   r   r   ú  s   € ÷ Pñ P°ñ Pr   c                 óÜ  € ^ RI Hp  ^ RIHpHp V ! 4       ;'       g    / pRp\        \        4      ;_uu_ 4        V! V4      pRRR4       \        \        4      ;_uu_ 4        \        W4R7      '       d   \        RR7       RRR4       \        \        4      ;_uu_ 4        V! RVR7       RRR4       R#   + '       g   i     Lz; i  + '       g   i     LO; i  + '       g   i     R# ; i)z5Cheap CLI-startup hint. Never restarts; never raises.rü   )rÿ   Úwarn_pending_manual_servesN)ru   rž   T)r  )r  rž   )	r!   rý   r   rÿ   r  r   rF   r  r  )rý   rÿ   r  ru   rž   s        r   Ú&_warn_pending_fleet_restart_on_startupr  ú  s•   € å=ßlá!Ó#×)Ð) r€GØ€NÜ	”)×	Õ	Ù5°gÓ>ˆ÷ 
ä	”)×	Õ	Ü%¨g×UÓUÜ'°Õ5÷ 
ô 
”)×	Õ	Ù"¨4ÀÕO÷ 
Ñ	÷ 
×	úç	×	ú÷ 
×	Ð	ús#   ¹	B4Á!CÂCÂ4C	ÃC	ÃC+	c              #  óâ   "  € \          F$  w  r \        V\        ,           ^
R7      pYT3x € K&  	  R#   \         d     K8  \        P
                   d   pT e	   T ! Y4        Rp?K^  Rp?ii ; i5i)zÿYield ``(scope, scope_cmd, list-units CompletedProcess)`` per systemd scope that answered.

A missing systemctl skips the scope silently; a listing timeout skips it after
``on_list_timeout(scope, exc)`` (when given) so the other scope is still processed.
©ÚtimeoutN)Ú_SYSTEMD_SCOPESÚ
_systemctlÚ_LIST_GATEWAY_UNITSÚFileNotFoundErrorÚ
subprocessÚTimeoutExpired)Úon_list_timeoutÚscopeÚ	scope_cmdÚresultrÌ   s   &    r   Ú_systemd_gateway_unit_listingsr!  
  sk   é € ÷ ,Ñˆð	Ü 	Ô,?Õ ?ÈÔLˆFð  Ð&Ô&ó ,øô !ô 	ÚÜ×(Ñ(ô 	ØÒ*Ù Ô+Ýûð	üs<   ‚A/�3§A/³A,¾A/ÁA,ÁA,ÁA'Á!A/Á'A,Á,A/c                ó0   € V ^8„  d   QhR\         R\        /# )r   r  r   rÜ   )r   s   "r   r   r     s   € ÷ ñ ”sð œtñ r   c                 ó|   € V R 8H  ;'       d1    \        \        R4      ;'       d    \        P                  ! 4       ^ 8g  # )r   Úgeteuid)ÚhasattrÚosr$  )r  s   &r   Ú_needs_sudor'    s;   € à�Ñ÷ 	ð 	Ü”B˜	Ó"÷	ð 	ä�JŠJ‹L˜AÑðr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# ©r   r  Úsvc_namer   ©r1   r0   Úint)r   s   "r   r   r   $  ó!   € ÷ ñ œdð ¬cð ´cñ r   c                óH  €  \        \        V 4      RVRR.,           ^
R7      p\        TR^4      ^ 8w  d   ^ #  \        \        TRR4      ;'       g    RP                  4       ;'       g    ^ 4      #   \        \        P                  3 d     ^ # i ; i  \         d     ^ # i ; i©zÞLive ``MainPID`` of a unit; ``0`` when inactive, unprivileged or unreadable.

Property reads need no manage-units privileges, and an unreadable PID is never collapsed:
identity that cannot be proved keeps its own restart.
Úshowú--property=MainPIDú--valuer  Ú
returncoder  r,   ©	r  r1   r#   r  r  Úgetattrr,  rØ   rÖ   ©r  r*  r   s   && r   Ú_unit_main_pidr7  $  ó¢   € ðÜœD ›O¨v°xÐAUÐW`Ð.aÕaÐkmÔnˆô ˆv�| QÓ'¨1Ô,ÙðÜ”G˜F H¨bÓ1×7Ð7°R×>Ñ>Ó@×EÐEÀAÓFÐFøô ”Z×.Ñ.Ð/ô Úðûô ô Úðúó.   ‚!A0 ¸B ÁB Á)B Á0BÂBÂB!Â B!c                ó(   € V ^8„  d   QhR\         RR/# )r   r}   r   N©r1   )r   s   "r   r   r   6  s   € ÷ 4uñ 4u´tð 4uÈ$ñ 4ur   c                óz  a aa€ ^ RI Hp \        4       o/ oV Fb  w  r4pSP                  V4       VP                  ^ 8w  d   S P                  RV R24       K?  \        VP                  W43V3R llV 3R lR7       Kd  	  \        S4      p/ p\        V4      ^8”  d   V! VV3R l4      w  rgVP                  4        F  w  r‰\        RV R	V	 R
24       K  	  V F”  p
SV
,          w  r4p\        WK4      '       g   K"  \        V4      R.,           p\        V4      '       d   RR.V,           p \        WËVR7      pVP                  ^ 8w  g   \        WK4      '       g   S P                  V4       K”  K–  	  S P%                  V3R l\&         4       4       R#   \         P"                   d    S P                  T4        Kâ  i ; i)uâ  Restart every hermes-gateway/serve unit ONCE PER LIVE HOST PROCESS.

One host runs one multiplexing gateway, so leftover per-profile units
(``hermes-gateway-<profile>.service``) all point at the SAME live ``MainPID``; restarting
each in turn restarts the host gateway N times â€” a self-inflicted N-fold outage triggered
by one update. Units that share a live main PID are collapsed to one representative and the
others are named as LEGACY units to migrate, never silently dropped.
©Ú collapse_units_to_host_processesúsystemd-z (listing failed)c                 ó6   <€ SP                  V R V  2WV 34      # ©Ú/©Ú
setdefault©r*  Ú_scopeÚ_cmdÚtargetss   &&&€r   Ú<lambda>Ú<_restart_systemd_gateway_units_best_effort.<locals>.<lambda>J  ó'   ø€ È×HZÑHZØ�(˜!˜H˜:Ð&¨°xÐ(@ôIBr   c                 ó&   <€ SP                  V 4      # r‰   )Úappend)r*  rÌ   r}   s   &&€r   rI  rJ  L  s   ø€ °&·-±-ÀÔ2Ir   ©Úprocess_unitÚon_unit_timeoutc                 óT   <€ \        SV ,          ^,          SV ,          ^,          4      # ©é   ©r7  ©re   rH  s   &€r   rI  rJ  T  ó   ø€ œn¨W°S­\¸!­_¸gÀc½lÈ1½oÔNr   õ     â€¢ úD is a legacy per-profile unit sharing one host gateway process with úl; restarting it again would restart that process twice. Fold the units together with: hermes gateway migrateú--no-ask-passwordÚsudoú-n©r  c              3   óF   <"  € T F  w  rVS9  g   K  R V R2x € K  	  R# 5i)r?  z (listing unavailable)NrI   )r“   r  Ú_Úanswereds   &  €r   r•   Ú=_restart_systemd_gateway_units_best_effort.<locals>.<genexpr>j  s)   øé € ÐtÉ?¹x¸uÐ^cÐksÑ^sÔ:�H˜U˜GÐ#9Õ:Ë?ùs   ƒ!“!N)r8   r>  rŸ   rµ   r3  rM  Ú_for_each_systemd_gateway_unitr  r1   rï   Úitemsr  Ú_systemd_unit_owned_by_updater'  Ú_systemctl_reset_and_restartÚ_wait_for_service_activer  r  r³   r  )r}   Úlistingsr>  r  r  r   ÚkeysrÂ   Úunit_keyÚ	owner_keyre   r*  Ú
manage_cmdr`  rH  s   f&           @@r   Ú*_restart_systemd_gateway_units_best_effortrl  6  s›  ú€ õ Sä‹u€HØ02€GÛ$,Ñ ˆ˜&Ø�‰�UÔØ×Ñ Ô!Ø�M‰M˜H U GÐ+<Ð=Ô>ÙÜ&Ø�M‰MØ16ö BäI÷		
ñ %-ô �‹=€DØ €GÜ
ˆ4ƒy�1„}á8ØÔNóP‰ˆà&Ÿ}™}žÑˆÜØ�X�JÐbØˆkð 4ð4ö	
ñ  /ó ˆØ%,¨S¥\Ñ"ˆ˜(Ü,¨Y×AÒAÙÜ˜)“_Ð(;Ð'<Õ<ˆ
Ü�u×ÒØ  $˜¨*Õ4ˆJð	$Ü1°*ÐR[Ô\ˆFØ× Ñ  AÔ%Ô-EÀi×-ZÒ-ZØ—‘˜hÖ'ñ .[ñ ð ‡M�MÔtÍ?ÓtÖtøô ×(Ñ(ô 	$Ø�M‰M˜(×#ð	$ús   Ä)A FÆ&F:Æ9F:c                óH   € V ^8„  d   QhR\         \        ,          R,          /# rH   )r1   r2   )r   s   "r   r   r   m  s   € ÷ ñ ¤$¤t¥*¨tÕ"3ñ r   c                 ó\  a€ \        4       oS'       g   R#  ^ RIHp  V ! 4       pT'       d   \        T4      f   R# \        ;QJ d    T3R lT 4       F  '       d   K   RM	  RM! T3R lT 4       4      '       d   T# R#   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)zÁThe fleet matrix when the probe finds at least one gateway and every row is ``current``
at the checkout SHA (identity known); ``None`` on any unknown/stale/down row or a failed
probe (restart).N)rÉ   z-Pending fleet restart: fleet probe failed: %sc              3   ó”   <"  € T F=  qP                  R 4      R8H  ;'       d    \        VP                  R4      4      S8H  x € K?  	  R# 5i)r�   rë   rŠ   N)rq   r0   )r“   rÃ   rÛ   s   & €r   r•   Ú+_live_fleet_current_rows.<locals>.<genexpr>|  s>   øé € Ð
gÑafÐZ]�7‰7�7Ó˜yÑ(×UÐU¬S°·±¸Ó1DÓ-EÈÑ-UÔUÓafùs
   ƒA¢&AFT)rs   r!   rÉ   rF   r;   r<   rÄ   rî   )rÉ   rŽ   rÌ   rÛ   s      @r   Ú_live_fleet_current_rowsrq  m  s…   ø€ ô )Ó*€LßÙðÝDÙ&Ó(ˆ÷ Ô+¨EÓ2Ò:Ùß
ƒsÔ
gÑafÓ
g‡s‡s‚sÔ
gÑafÓ
g×gÒgØˆÙøô ô Ü�‰ÐDÀcÔJÝûðús   —A? Á?B+Â
B&Â&B+c                ó$   € V ^8„  d   QhR\         /# r'   r@   )r   s   "r   r   r   �  s   € ÷ ñ œsñ r   c                 ó  € \        4       p V '       d   \        V 4      # \        4       ;'       g    / P                  R4      ;'       g    RP	                  4       p V '       d   V # \        \        4      ;_uu_ 4        ^ RIHp V! 4       ;'       g    / P                  R4      p\        V\        4      '       d/   \        VP                  R4      ;'       g    R4      uuRRR4       #  RRR4       R#   + '       g   i     R# ; i)uæ  The SHA a completed host restart is stamped with; ``""`` when nothing names the code.

``_current_checkout_sha()`` is ``None`` on every non-git install (zip, pip, Docker), and an
empty stamp can never match, so the per-host restart-once guard would be inert exactly on the
installs it exists for: each profile's ``hermes update`` would re-kill the one shared
multiplexer. The obligation's own ``expected_sha`` â€” else the receipt's post-update identity â€”
names the same pulled code.
r+   r,   rü   rõ   rn   N)rs   r0   rh   rq   rØ   r   rF   r!   rý   r€   r2   )rn   rý   rõ   s      r   Ú_restart_identity_shart  �  sÀ   € ô  Ó
!€Cß
Ü�3‹xˆÜÓ ×&Ð& B×+Ñ+¨NÓ;×AÐA¸r×
HÑ
HÓ
J€Cß
Øˆ
Ü	”)×	Õ	ÝAÙ*Ó,×2Ð2°×7Ñ7¸ÓFˆÜ�k¤4×(Ò(Ü�{—‘ uÓ-×3Ð3°Ó4÷	 
Ò	ð )÷ 
ñ
 ÷ 
Ö	ñ
 ús   Á:AC0ÃC0Ã0D	c                ó2   € V ^8„  d   QhR\         R,          /# rH   r@   )r   s   "r   r   r   ˜  s   € ÷ ñ ¬¨d­
ñ r   c                óH  a€ ^ RI Hp \        4       oV! S4      '       d   R# S'       dy   V eu   V P                  '       dc   \        ;QJ d)    V3R lV P                   4       F  '       d   K   RM	  RM! V3R lV P                   4       4      '       d   \        4       e   R# R# )u  Why the completion tail may leave the fleet alone, or ``None`` when a restart is owed.

Every route (pulled, already-current, ZIP) now finishes through the same completion
tail, so the guards the old catch-up path carried live here: one host runs ONE
multiplexing gateway, so a second profile's ``hermes update`` attaches to the restart the
first one already stamped (#95294), and a fleet already serving the checkout code (a
no-op update, a manual ``hermes gateway restart`` seconds ago) is not re-killed (#117051).

The second guard needs BOTH the pre-update plan and the live probe: the live matrix only
lists gateways, so a planned ``serve`` still on pre-update code (or any runtime without a
stamped identity) keeps the restart â€” the reconciliation there is what surfaces it.
)Úhost_restart_already_completedz9this host's gateway was already restarted for this updateNc              3   óT   <"  € T F  p\        VP                  4      S8H  x € K  	  R # 5ir‰   )r0   rŠ   )r“   r™   rÛ   s   & €r   r•   Ú-_fleet_restart_skip_reason.<locals>.<genexpr>ª  s!   øé € ÐWÉ¸g”C˜×(Ñ(Ó)¨\Ö9Ëùs   ƒ%(FTz6every running gateway already serves the checkout code)r8   rw  rt  r-   rî   rq  )r—   rw  rÛ   s   & @r   Ú_fleet_restart_skip_reasonrz  ˜  sg   ø€ õ QÜ(Ó*€LÙ% l×3Ò3ÙJß˜Ò)¨d¯m¯m¨mß“ÔWÈÏÊÓW——’ÔWÈÏÊÓW×WÒWÜ(Ó*Ò6ÙGÙr   c                ó$   € V ^8„  d   QhR\         /# r'   r   )r   s   "r   r   r   °  s   € ÷ 'ñ '¤Dñ 'r   c                 ó$   € ^ RI Hp  V ! RR7       R# )zEHistorical retry hook; new retries use the ordinary completion owner.©Ústop_for_relaunchT)rz   N)Úhermes_cli._old_updaterr~  r}  s    r   Ú_run_pending_fleet_restartr€  °  s   € å9Ù ×&r   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úcmdr  )r1   Úfloat)r   s   "r   r   r   ¶  s   € ÷ Añ A”Dð A¤eñ Ar   c          
     ó<   € \         P                  ! V RRRRVRR7      # )zTRun a systemctl (or sudo systemctl) invocation, capturing utf-8 text with a timeout.Túutf-8ÚreplaceF©Úcapture_outputrb   r[   Úerrorsr  Úcheck)r  Úrun)r‚  r  s   &$r   r  r  ¶  s&   € ä�>Š>˜#¨d¸ÈÐXaÐkrÐzô  Að  Ar   r  c                óJ   € V ^8„  d   QhR\         R\        R\         R,          /# )r   rk  r*  r  N)r1   r0   )r   s   "r   r   r   »  s-   € ÷ Kñ K¬Tð K¼Sð KÔPTÐW[ÕP[ñ Kr   c               ó„   € ^ RI Hp T! Ve   TMT V4      p\        V RV.,           ^
R7       \        V RV.,           VR7      # )z¦``reset-failed`` then ``restart``: a unit parked in failed state by systemd's own
auto-restart can wedge a plain ``restart`` against RestartSec backoff and stay dead.)Úsystemd_restart_timeoutúreset-failedr  Úrestart)Ú'hermes_cli.update_cmd_fleet_unit_budgetrŽ  r  )rk  r*  r  rŽ  r  s   &&$  r   re  re  »  sG   € õ
 PÙ%°9Ò3H¡iÈjÐZbÓc€GÜˆz˜^¨XÐ6Õ6ÀÕCÜ�j I¨xÐ#8Õ8À'ÔJÐJr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# r)  )r1   r0   r   )r   s   "r   r   r   Æ  s!   € ÷ ñ ¬Tð ¼Sð ÄTñ r   c                óv   € ^ RI HpHpHp V! W4      pVe   V! V4      '       d   R# \	        V! RW4      4       R# )a•  Gate a unit restart on the unit's home being one this update owns (#93349).

``hermes-gateway*`` is an account-wide namespace: a second install's ``hermes update`` used
to drain and restart the account's real ``hermes-gateway.service`` because the unit was
listed, not because it ran the updated code. Foreign or unreadable ownership prints a notice
and leaves the unit alone; it is not a failed restart.
)Údescribe_skipped_runtimeÚsystemd_unit_hermes_homeÚhome_in_update_scopeTzsystemd unitF)Úhermes_cli.update_fleet_scoper”  r•  r–  r  )r  r*  r”  r•  r–  Úhomes   &&    r   rd  rd  Æ  s<   € ÷ wÑvÙ# IÓ8€DØÒÑ0°×6Ò6ÙÜ	Ñ
" >°8Ó
BÔCÙr   ÚkeepÚquietc                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r   rš  r   )r   r1   r,  )r   s   "r   r   r   Ö  s"   € ÷ 	@ñ 	@¼ð 	@Ì$ÌsÍ)ñ 	@r   c               ó  € ^ RI HpHp \        V4      pT! V  Uu. uF  qUV9  g   K  VNK  	  up4      w  rgV'       g"   V F  w  rX\	        V! RRV 2V4      4       K  	  V  Uu. uF  qUV9   g	   WV9   g   K  VNK  	  up# u upi u upi )z¦*pids* whose live home this update owns (plus *keep*, PIDs already mapped to this
install's profile PID files); every other gateway process is named and left running.)r”  Úpartition_gateway_pids_by_scopezgateway processzPID )r—  r”  r�  rŸ   r  )	Úpidsr™  rš  r”  r�  ÚpidÚownedÚforeignr˜  s	   &$$      r   Ú_scoped_manual_gateway_pidsr¢  Ö  s†   € ÷ hÜˆt‹9€DÙ4ÁTÓ5]ÁT¸cÐX\É_·c°cÁTÑ5]Ó^�N€EßÛ ‰IˆCÜÑ*Ð+<ÀÀSÀE¸lÈDÓQÖRñ !áÓ?™4�C¨$¤;°#±,�CˆC™4Ñ?Ð?ùò	 6^ùò @s   šA?§A?Á#BÁ6Bc                ó0   € V ^8„  d   QhR\         R\        /# ©r   Úunitr   rÜ   )r   s   "r   r   r   â  s   € ÷ 
ñ 
¤cð 
¬dñ 
r   c                óŠ   € V R8H  ;'       g8    V P                  R4      ;'       g    V R8H  ;'       g    V P                  R4      # )z]``hermes-serve*``/``hermes-dashboard*`` (``.service``) by the same exact-or-hyphenated shape.zhermes-serve.servicezhermes-serve-zhermes-dashboard.servicezhermes-dashboard-©Ú
startswith©r¥  s   &r   Ú_is_serve_or_dashboard_unitrª  â  sV   € ð 	Ð&Ñ&÷ 	0ð 	0Ø�?‰?˜?Ó+÷	0ð 	0ð
 Ð-Ñ-÷	0ð 	0ð �?‰?Ð.Ó/ðr   c                ó0   € V ^8„  d   QhR\         R\        /# r¤  rÜ   )r   s   "r   r   r   ï  s   € ÷ 	ñ 	¤#ð 	¬$ñ 	r   c                ód   € V R8H  ;'       g%    V P                  R4      ;'       g    \        V 4      # )zyExact base unit or hyphenated profile family only: ``startswith("hermes-serve")``
would accept ``hermes-server.service``.zhermes-gateway.serviceúhermes-gateway-)r¨  rª  r©  s   &r   Ú_is_hermes_gateway_unitr®  ï  s;   € ð 	Ð(Ñ(÷ 	-ð 	-Ø�?‰?Ð,Ó-÷	-ð 	-ä& tÓ,ðr   c                ó(   € V ^8„  d   QhR\         RR/# )r   Úlist_units_stdoutr   Nr@   )r   s   "r   r   r   û  s   € ÷ +ñ +´cð +Ð`dñ +r   c               óˆ  € T ;'       g    RP                  4       P                  4        Fj  pVP                  4       pV'       g   K  V^ ,          pVP                  R4      '       d   \	        V4      '       g   KP  VP                  R4      p V! V4       Kl  	  R#   \        P                   d   pT! Yg4        Rp?K“  Rp?ii ; i)zôProcess each hermes-gateway*/hermes-serve* unit from ``systemctl list-units``.

``TimeoutExpired`` from ``process_unit`` is isolated per unit via ``on_unit_timeout``
so one wedged systemctl call cannot abort the rest of the fleet.

See #68523.
r,   ú.serviceN)rØ   r_   ÚsplitÚendswithr®  Úremovesuffixr  r  )r°  rO  rP  rd   Úpartsr¥  r*  rÌ   s   &$$     r   rb  rb  û  sŸ   € ð #×(Ð( b×/Ñ/Ó1×<Ñ<Ö>ˆØ—
‘
“ˆßÙØ�Q�xˆØ�}‰}˜Z×(Ò(Ô0GÈ×0MÒ0MÙØ×$Ñ$ ZÓ0ˆð	+Ù˜Ö"ó ?øô ×(Ñ(ô 	+Ù˜H×*Ò*ûð	+ús   ÂBÂCÂ.B<Â<Cc                ó0   € V ^8„  d   QhR\         R\        /# )r   r*  r   rÜ   )r   s   "r   r   r     s   € ÷ 
Rñ 
R¼cð 
RÄdñ 
Rr   c                ó>   € V R8H  ;'       g    V P                  R4      # )a†  Whether *svc_name* wires SIGUSR1 to a graceful drain-then-restart.

Only ``hermes-gateway*`` runs ``gateway/run.py`` (the handler); SIGUSR1 would just
kill ``hermes-serve*`` and burn the drain budget, so those go straight to the blunt
restart. Same exact/hyphenated shape as ``_for_each_systemd_gateway_unit`` so a
near-prefix unit like ``hermes-gatewayd`` is never signalled.

See #83438.
zhermes-gatewayr­  r§  )r*  s   &r   Ú/_service_unit_supports_graceful_sigusr1_restartr¹    s$   € ð Ð'Ñ'×QÐQ¨8×+>Ñ+>Ð?PÓ+QÐQr   c                ó(   € V ^8„  d   QhR\         RR/# )r   Úfailed_unitsr   Nr;  )r   s   "r   r   r     s   € ÷ Vñ V¼ð VÀ$ñ Vr   c                ó¶  € ^ RI Hp V '       g   R# \        \        P	                  V 4      4      p\        4        \        R4       V F  p\        RV 24       K  	  V! 4       '       d:   \        R4       \        R4       \        R4       \        R4       \        R	4       R# \        R
4       \        R4       \        R4       \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        R4       \        R4       \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        R4       R# R# )zBPrint an explicit incomplete-update warning for unrestarted units.)Úis_macosNu8   âš  Update incomplete â€” some units were not restarted:z    - z<  Listed services may be deregistered from launchd, or stillz<  running pre-update code (mixed sys.modules). Recover with:ú    hermes gateway statusz!    launchctl list | grep <label>zI    launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/<label>.plistz;  Skipped units may still be running pre-update code (mixedz3  sys.modules). Restart them manually, then verify:c              3   óL   "  € T F  qP                  R 4      '       * x € K  	  R# 5i©z
ai.hermes.Nr§  ©r“   Únames   & r   r•   Ú9_warn_incomplete_gateway_fleet_restart.<locals>.<genexpr>5  s   é € Ð
A¹°�‰˜|Ó,×,Ñ,»ùs   ‚"$TFz2    systemctl --user restart <unit>   # user-scopez4    sudo systemctl restart <unit>     # system-scopec              3   óB   "  € T F  qP                  R 4      x € K  	  R# 5irÀ  r§  rÁ  s   & r   r•   rÃ  8  s   é € Ð
=±W¨T�?‰?˜<×(Ð(³Wùó   ‚zD    launchctl kickstart -k gui/$UID/<label>   # macOS (or user/$UID))Úhermes_cli.gatewayr½  r1   r2   Úfromkeysr  rš   )r»  r½  ÚorderedrÂ  s   &   r   Ú&_warn_incomplete_gateway_fleet_restartrÉ    sú   € å+ßÙÜ”4—=‘= Ó.Ó/€GÜ	„GÜ	Ð
DÔEÛˆÜ��t�fˆoÖñ á‡z‚zô 	ÐLÔMÜÐLÔMÜÐ)Ô*ÜÐ1Ô2ÜÐYÔZÙÜ	Ð
GÔHÜ	Ð
?Ô@Ü	Ð
%Ô&ß
ƒsÑ
A¹Ó
A‡s‡s‚sÑ
A¹Ó
A×AÒAÜÐBÔCÜÐDÔEß
ƒsÑ
=±WÓ
=‡s‡s‚sÑ
=±WÓ
=×=Ò=ÜÐTÖUñ >r   Úsupervision_verifyTÚself_restart_pendingc                ól   € V ^8„  d   QhR\         R\        R,          R\        \        \        3,          /# )r   rÊ  rË  Nr   )r   rŸ   r    r1   )r   s   "r   r   r   <  s6   € ÷ Kñ KÜðKÜ>AÀD½jðKä
Œ4”ˆ:ÕñKr   c                óÆ  € ^ RI HpHpHpHpHpHp V! 4       pRp	 V! 4       P                  4       '       g   . . 3# V '       d	   V! V4      MRp	 V! 4        T '       g   T.. 3# T	e)   T! T	4      '       d   Te   TP#                  T	4       T.. 3# T! Y‰R
7      '       d   T.. 3# \        RT R24       . T.3#   \        P                   dD   p
\        T
RR4      ;'       g    RP                  4       p\        RT R24       . T.3u Rp
?
# Rp
?
ii ; i  \        \        P                  3 d6   p
\        RT
P                  P                    RT
 R	24       . T.3u Rp
?
# Rp
?
ii ; i)uþ  Restart the invoking profile's launchd gateway after an update.

No ``launchctl list`` gating: a booted-out job (plist present, definition
deregistered) fails it, and it can exit non-zero while the job is alive â€” gating on it
silently skipped the restart yet printed "Update complete!". When the plist exists
``launchd_restart()`` always runs; every failure path is loud with a manual recovery
command. Returns ``(restarted_labels, failed_labels)``; with ``supervision_verify``
success also requires a fresh supervised PID ("the call returned" is not "supervised").

74973 (salvage #75021 by @jeff-mettel): the restart used to be gated on ``launchctl list <label>``
exiting 0. A *booted-out* job â€” plist present, definition deregistered from launchd (crashed helper,
manual bootout, failed prior update) â€” fails that check, so the whole branch silently skipped: no
restart, no message, ``KeepAlive`` unable to revive a definition launchd no longer knows, and the update
still printed "Update complete!".
See #88848.
)Úget_launchd_labelÚget_launchd_plist_pathÚlaunchd_restartÚ$wait_for_launchd_gateway_supervisionÚ#_is_pid_ancestor_of_current_processÚ_launchctl_supervised_pidNr  r,   u     âš  Gateway restart failed: zY
    The gateway may be DOWN on pre-update code. Recover manually: hermes gateway restartu%     âš  Could not restart the gateway (ú: z/).
    Recover manually: hermes gateway restart)rL   Úold_pidõ     âœ— zl restarted but launchd is not supervising a new process for it.
    Check logs, then: hermes gateway restart)rÆ  rÎ  rÏ  rÐ  rÑ  rÒ  rÓ  Úexistsr  ÚCalledProcessErrorr5  rØ   r  r  r  Ú	__class__Ú__name__rµ   )rÊ  rË  rÎ  rÏ  rÐ  rÑ  rÒ  rÓ  Úcurrent_labelrÕ  Úer  s   $$          r   Ú%_restart_launchd_gateway_after_updaterÝ  <  s›  € ÷&÷ ñ &Ó'€MØ€Gð#Ù%Ó'×.Ñ.×0Ò0Ø�r�6ˆM÷ ?QÑ+¨MÔ:ÐVZˆð		'ÙÔ÷( Øˆ Ð"Ð"ØÒÑBÀ7×KÒKð  Ò+Ø ×$Ñ$ WÔ-Øˆ Ð"Ð"ñ ,°-×QÓQØˆ Ð"Ð"Ü	Ø
��ð  7ð 	7ôð �ˆÐÐøôS ×,Ñ,ô 	'Ü˜a ¨2Ó.×4Ð4°"×;Ñ;Ó=ˆFÜØ0°°ð 9;ð ;ôð
 ˜�Ð&Õ&ûð	'ûô œz×8Ñ8Ð9ô 	#ô 	ðØ—‘×$Ñ$Ð% R¨ sð +;ð;ô	
ð �M�?Ð"Õ"ûð	#úsW   ›D ¶D ºD Á
D ÁB5 Â5DÃ
8DÄDÄD ÄDÄD ÄE Ä+*EÅE ÅE Úrequire_supervisionc                óf   € V ^8„  d   QhR\         R\         R\        R\        R\        R,          RR/# )r   Úrestarted_servicesÚfailed_or_stale_unitsÚdrain_budgetrÞ  rË  Nr   )r1   rƒ  r   rŸ   )r   s   "r   r   r   Š  sR   € ÷ [gñ [gÜð[gÜ59ð[gÜINð[gÜhlð[gä �*ð[gð 
ñ[gr   c               ó*  € ^ RI HpHpHpHpHp	Hp
HpHp V'       dD   \        P                  ! RR.RRRR^
RR7      pVP                  ^ 8w  d   VP                  R	4       R
# ^ RIHp V! 4       pV! 4       R,          pVV9   d   . . 3M\        RVR7      w  ppV P!                  V4       VP!                  V4       V! 4       pV! \#        V4      V0,          R7      pV'       d   \%        RRP'                  V4       24       ^ RIHpHp VV,            EFQ  pVV8X  g   VV9   d   K  V! V4      ;pe   \%        V! RVV4      4       K5   V! V4      w  ppVfI   V'       d?   V! 4       P/                  V R24      P1                  4       '       d   VP                  V4       K�  RpVe=   V^ 8”  d6   \%        RV RVR R24       ^ RIHp V	! VVV! \7        V4      VR7      R7      pV'       d&   V! VVRVR7      '       d   V P                  V4       Kü   V
! VV4       T! TTR#TR7      '       d   T P                  T4       EK,  TP                  T4       \%        R$T R%T R"T 24       EKT  	  R
#   \        P8                   dZ   p\;        TRR4      ;'       g    RP=                  4       pTP                  T4       \%        RT R T R!T R"T 24        R
p?EKÁ  R
p?ii ; i  \        P>                   d&    TP                  T4       \%        R&T R'24        EK  i ; i)(uí  Restart every launchd-managed gateway after an update (macOS).

The pull is shared across profiles, so every ``ai.hermes.gateway*`` LaunchAgent
must reload it or siblings stay on pre-update ``sys.modules`` (systemd parity).
Invoking profile uses ``launchd_restart()``; siblings get the same drain-first
sequence with their domain (``gui/<uid>`` vs ``user/<uid>``) resolved per label so
none is kickstarted in the wrong domain. ``TimeoutExpired`` is isolated per label.

See #41403.
The invoking profile keeps the existing ``launchd_restart()`` treatment (self-restart request â†’ graceful
drain â†’ kickstart). ``subprocess.TimeoutExpired`` is isolated per label so one wedged launchctl call
cannot leave the rest of the fleet on old code (#68523).
)rÎ  rÏ  Ú"launchd_gateway_labels_for_installÚ!legacy_launchd_labels_for_installÚ_graceful_restart_via_sigusr1Ú_launchd_kickstartÚ_locate_launchd_gateway_serviceÚ_wait_for_launchd_service_pidÚ	launchctlr1   Tr…  r†  Fr‡  zlaunchd (listing failed)N©Úalready_restartedÚlabels)rÊ  rË  )Úexcludeu>     â†» legacy-labelled units of this install join the restart: ú, )r”  Úlaunchd_label_foreign_homezlaunchd jobz.plistõ     â†’ ú: draining (up to ú.0fús)...©Údrain_progress_reporter©Úbudget_s©Údrain_timeoutÚon_progressç      $@)rÕ  r  Údomainr  r,   õ     âš  Failed to restart rÔ  z.
    Recover manually: launchctl kickstart -k rB  g      .@rÖ  zQ failed to come back after restart.
    Check logs, then: launchctl kickstart -k u%     âš  launchctl timed out restarting z$; continuing with remaining gateways) rÆ  rÎ  rÏ  rä  rå  ræ  rç  rè  ré  r  r‹  r3  rM  Ú!hermes_cli.update_cmd_posix_pauserì  rÝ  r³   rŸ   r  Újoinr—  r”  rð  Ú	with_namer×  Ú"hermes_cli.update_cmd_drain_reportrö  Ú_gateway_home_for_pidrØ  r5  rØ   r  )rà  rá  râ  rÞ  rË  rÎ  rÏ  rä  rå  ræ  rç  rè  ré  Úlistingrì  rÛ  ÚresumedÚ
_restartedÚ_failedÚderived_labelsÚlegacy_labelsr”  rð  rL   Úforeign_homerý  rÕ  Úgraceful_okrö  rÜ  r  s   &&&$$                          r   Ú_restart_macos_launchd_gatewaysr  Š  s4  € ÷"÷ ó ÷
 Ü—.’. +¨vÐ!6ÀtÐRVÐahÐqzð  EGð  OTô  UˆØ×Ñ Ô"Ø!×(Ñ(Ð)CÔDÙÝCÙ%Ó'€MÙÓ! (Õ+€GØ&3°wÔ&>˜2˜r™(ÔDiØÐ6JôELÑ€J�à×Ñ˜jÔ)Ø× Ñ  Ô)á7Ó9€Nñ
 6¼cÀ.Ó>QÐUbÐTcÕ>cÔd€MßÜÐNÈtÏyÉyÐYfÓOgÐNhÐiÔjßbØ -×/Ñ/ˆØ�MÔ! U¨gÔ%5Ùñ 7°uÓ=Ð=ˆLÒJÜÑ*¨=¸%ÀÓNÔOÙð'	gñ >¸eÓD‰OˆF�GØŠ~ß&Ñ+AÓ+C×+MÑ+MÐQVÐPWÐW]ÐN^Ó+_×+fÑ+f×+hÒ+hØ)×0Ñ0°Ô7ÙØˆKØÒ" w°¤{Ü˜˜u˜gÐ%7¸ÀSÐ7IÈÐOÔPÝVÙ;Ø¨<Ù 7Ô8MÈgÓ8VÐamÔ nôp�÷ Ñ<¸UÈGÐ]aÐjp×qÓqà"×)Ñ)¨%Ô0Ùð	Ù" 5¨&Ô1ñ -¨U¸GÈTÐZ`×aÓaØ"×)Ñ)¨%×0à%×,Ñ,¨UÔ3ÜØ˜U˜Gð $DØDJÀ8È1ÈUÈGðU÷óS 0øô: ×0Ñ0ô Ü! ! X¨rÓ2×8Ð8°b×?Ñ?ÓA�Ø%×,Ñ,¨UÔ3ÜØ.¨u¨g°R¸°xð @DØDJÀ8È1ÈUÈGðUôö ûðûô  ×(Ñ(ô 	gØ!×(Ñ(¨Ô/ÜÐ9¸%¸Ð@dÐe×fÐfð	gúsh   ÅKÅ,KÆ	KÆA	KÇ&KÇ8KÈ	I'ÈKÈ'KÈ;%KÉ'KÉ<AKË	KËKËKË5LÌLc                 ó–   €  ^ RI Hp  \        V ! RR7      RR7      #   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)a/  Best-effort PIDs of gateways still running after the restart phase died.

``None`` when undeterminable (notably ``hermes_cli.gateway`` no longer importing
under the replaced checkout). Callers treat ``None`` and non-empty as "assume
stale"; only a positive empty result proves nothing needs restarting.
)Úfind_gateway_pidsT©Úall_profiles©rš  z7Could not probe for surviving gateways after update: %sN)rÆ  r  r¢  rF   r;   r<   )r  rÌ   s     r   Ú,_surviving_gateway_pids_after_failed_restartr  è  sA   € ðÝ8Ü*Ñ+<È$Ô+OÐW[Ô\Ð\øÜô Ü�‰ÐNÐPSÔTÝûðús   ‚ œA§AÁAz_manual gateway has no supervisor relaunch authority; left running for explicit operator restartzudesktop app owns and respawns this serve backend; the recovery pass must not restart it out from under its supervisorzÐno per-profile relaunch command reaches a serve/dashboard runtime; recovered by the fresh systemd unit pass when a hermes-serve*/hermes-dashboard* unit owns it, else left running for explicit operator restartz¡launchd job owns this backend; the post-update dashboard cleanup kickstarts the job through launchd, never a detached argv respawn that would fight its KeepAliveÚskip_profilesc                ó®   € V ^8„  d   QhR\         \        ,          R,          R\        \        \        \        3,          \        \        ,          3,          /# )r   r  Nr   )rŸ   r0   r    r2   r1   )r   s   "r   r   r     sA   € ÷ (ñ (¼¼C½À4½ð (ÔSXÔY]Ô^aÔcfÐ^fÕYgÔimÔnrÕisÐYsÕStñ (r   c               ó˜  € T;'       g    \        4       p/ p. p\        R4      ;_uu_ 4        \        V RR4      ;'       g    R Fä  p\        VRR4      p\        VRR4      p\        VRR4      p\        V\        4      '       d	   V'       g   KJ  VR8X  d8   Wa9   d   KY  V\
        9   d   VP                  V\	        V4      4       K�  \        pM1VR9   d)   ^ RIH	p	 Wy9   d   \        pMVR	8X  d   \        pM	\        pMK¹  VP                  RVR\	        V4      R\	        V4      R
V/4       Kæ  	  RRR4       W#3#   + '       g   i     Y#3# ; i)ue  Partition pre-update runtimes into fresh-restart candidates and skips.

Uses only the pre-checkout inventory: re-importing ``hermes_cli.gateway`` in the
failing interpreter is what raises the original ``ImportError``. Returns
``(candidates, skipped)``: profile â†’ supervisor for supervised gateways the fresh
process may restart; every other inventoried runtime with an explicit reason so
nothing vanishes silently. Skipped serve/dashboard is NOT unrecoverable: the fresh
child's ``hermes-serve*`` systemd pass enumerates units from systemd; leftovers are
caught by :func:`_surviving_pre_update_serve_runtimes`.
z4Could not prepare fresh gateway restart profiles: %sr-   r­   Nr7   r®   r¬   )ÚCLIENT_OWNED_SERVE_SUPERVISORSÚlaunchdÚreasonrI   r°   )rŸ   r   r5  r€   r0   Ú_FRESH_RESTART_SUPERVISORSrD  Ú_MANUAL_GATEWAY_SKIP_REASONÚhermes_cli.update_inventoryr  Ú_DESKTOP_SERVE_SKIP_REASONÚ_LAUNCHD_SERVE_SKIP_REASONÚ_SERVE_SKIP_REASONrM  )
r—   r  Ú
candidatesÚskippedr™   r­   r7   r®   r  r  s
   &$        r   Ú_gateway_recovery_partitionr!    s5  € ð "×*Ð*¤S£U€MØ!#€JØ€GÜ	ÐL×	MÕ	MÜ˜t Z°Ó4×:Ð:¸Ò:ˆGÜ˜7 F¨DÓ1ˆDÜ˜g y°$Ó7ˆGÜ  ¨,¸Ó=ˆJÜ˜g¤s×+Ò+·7ÙØ�yÔ ØÔ+ÙØÔ!;Ô;Ø×)Ñ)¨'´3°z³?ÔCÙÜ4‘ØÐ/Ô/ÝVàÔ?Ü7‘FØ 9Ô,Ü7‘Fä/‘FáØ�N‰N˜I w°¼¸D»	À<ÔQTÐU_ÓQ`ÐbjÐlrÐsÖtñ1 ;÷ 
Nð4 ÐÐ÷5 
NÖ	Mð4 ÐÐús   ¬AD7ÂB D7Ä7E		c                ó(   € V ^8„  d   QhR\         RR/# )r   rÌ   r   N)ÚBaseException)r   s   "r   r   r   ;  s   € ÷ 'ñ '¬]ð 'ÀTñ 'r   c                ó  € \        4        \        RV  24       V'       d(   RP                  R V 4       4      p\        RV 24       M\        R4       \        R4       \        R4       \        R4       \        R	4       R
# )a)  Print a recovery warning when the whole restart phase raised.

Previously a blanket debug-logged ``except Exception`` erased every drain/restart
line, so "Update complete!" exited 0 while the gateway kept serving pre-update
modules and died on the next turn with an ImportError.

Issue #78574: the gateway auto-restart phase was wrapped in a blanket ``except Exception`` that only
logged at debug level, so an early failure (e.g. importing ``hermes_cli.gateway`` from the freshly
pulled checkout) erased every drain/restart line from the update output.
u7   âš  Update incomplete â€” gateway auto-restart failed: rï  c              3   ó8   "  € T F  p\        V4      x € K  	  R # 5ir‰   r@   )r“   rŸ  s   & r   r•   Ú6_warn_gateway_restart_phase_aborted.<locals>.<genexpr>I  s   é € Ð4©t¨œ3˜sŸ8˜8«tùs   ‚z5  Gateway process(es) still running pre-update code: z6  Any gateway still running is serving pre-update codez3  (mixed sys.modules) against the updated checkout.z#  Restart it manually, then verify:z    hermes gateway restartr¾  N)r  r   )rÌ   rž  Úlisteds   && r   Ú#_warn_gateway_restart_phase_abortedr(  ;  sm   € ô 
„GÜ	ÐCÀCÀ5Ð
IÔJßØ—‘Ñ4©tÓ4Ó4ˆÜÐEÀfÀXÐNÕOäÐFÔGÜÐCÔDÜ	Ð
/Ô0Ü	Ð
&Ô'Ü	Ð
%Ö&r   c          
      ób   € V ^8„  d   QhR\         R\        R\        R\        R,          R\        /# )r   rŸ  râ  rL   rË  Nr   )r,  rƒ  r0   rŸ   r   )r   s   "r   r   r   S  s?   € ÷ *`ñ *`Ü	ð*`Ü!ð*`Ü*-ð*`ÜHKÈdÍ
ð*`ä	ñ*`r   c          	     ó^  € ^ RI HpHpHpHpHpHp	 V! V 4      '       d7   \        RV R24       V! V 4      p
V
'       d   Ve   VP                  V 4       V
# V	! V 4      V8X  d   \        RV R24       V! V 4       R# \        RV RVR R	24       ^ R
I	H
p V! WV! \        V 4      VR7      R7      # )u�  Three-way triage (shared by systemd and bare-process paths) for handing a
running gateway over to new code. Returns True when signalled/stopped.

1. Gateway is an ancestor of this process (auto-update cron inside the gateway
   tree): waiting is circular (gateway waits on in-flight work â†’ cron session
   waits on update â†’ update waits on gateway) and the 1800s force-drain cap burns.
   So fire-and-forget: signal restart and return; it completes once THIS process exits.
   The pid lands in ``self_restart_pending`` so the fleet matrix can tell "restart
   deferred until the updater exits" from "restart never happened" (#119597): the
   ancestor is still serving the old code when the matrix runs, by construction.
2. Event loop provably wedged: SIGUSR1 can never drain it; bounded SIGTERMâ†’SIGKILL.
3. Live out-of-tree gateway: graceful SIGUSR1 drain up to ``drain_budget``.

The wedged-loop probe cannot break it: the cron session posts activity every ~180s (process-tool poll
return), so it is "actively waiting forever" and never marked wedged â€” the gateway burns the full
force-drain cap (1800s) before killing its own updater's session. See #86684.
)ÚGATEWAY_LOOP_WEDGEDÚ_escalate_wedged_gatewayræ  rÒ  Ú_request_gateway_self_restartÚprobe_gateway_loop_livenessrñ  u�   : update is running inside this gateway's process tree â€” signalling restart and letting the gateway drain itself (avoids the cron-update deadlock, #100179)õ     âš  uR   : gateway event loop is unresponsive â€” skipping drain, forcing a bounded stop...Trò  ró  rô  rõ  r÷  rù  )rÆ  r+  r,  ræ  rÒ  r-  r.  r  rµ   r  rö  r  )rŸ  râ  rL   rË  r+  r,  ræ  rÒ  r-  r.  Úacceptedrö  s   &&&$        r   Ú#_drain_or_signal_gateway_for_updater1  S  sÈ   € ÷(÷ ñ +¨3×/Ò/ÜØ�U�Gð Fð Fô	
ñ
 1°Ó5ˆßÐ,Ò8Ø ×$Ñ$ SÔ)ØˆÙ" 3Ó'Ð+>Ô>Ü��u�gÐoÐpÔqÙ  Ô%ÙÜ	ˆF�5�'Ð+¨L¸Ð+=¸UÐ
CÔDÝJÙ(ØÙ+Ô,AÀ#Ó,FÐQ]Ô^ô`ð `r   c                ó$   € V ^8„  d   QhR\         /# )r   rŸ  )r,  )r   s   "r   r   r   €  s   € ÷ 	ñ 	œsñ 	r   c                ó   € \        \        4      ;_uu_ 4        ^ RIHp ^ RIHp V! 4        FB  w  r4V! VR,          4      ;'       g    / pVP                  R4      V 8X  g   K6  Vu uuRRR4       # 	  RRR4       R#   + '       g   i     R# ; i)z[HERMES_HOME of the gateway ``pid`` per the fleet inventory, else None (own profile's file).)Ú_profile_homes)Úread_runtime_statuszgateway_state.jsonrŸ  N)r   rF   r!   r4  Úgateway.statusr5  rq   )rŸ  r4  r5  Ú_profiler˜  Úrecords   &     r   r  r  €  sp   € ä	”)×	Õ	Ý<Ý6Ù,Ö.‰NˆHÙ(¨Ð0DÕ)DÓE×KÐKÈˆFØ�z‰z˜%Ó  CÖ'Ø‘÷ 
Ò	ñ /÷ 
ñ ÷ 
Ö	ñ ús   ˜.A<ÁA<Á"A<Á0A<Á<B	c                ó0   € V ^8„  d   QhR\         R\        /# )r   Útargeted_prober   )r1   r   )r   s   "r   r   r   Œ  s   € ÷ ñ ¬Dð ´Tñ r   c                óø   €  \         P                  ! . ROR^RR7      P                  ^ 8X  d   R# \         P                  ! RR.V OR^RR7      P                  ^ 8H  #   \        \         P                  3 d     R# i ; i)uU  True when this user can elevate without a prompt.

``sudo -n true`` first; a refusal is inconclusive because a NOPASSWD sudoers entry scoped
to one command (the hardened shape) rejects the blanket probe, so fall back to running
``sudo -n <targeted_probe>`` â€” callers pass a non-destructive stand-in for the argv they
are about to elevate.
r[  r\  TF)rˆ  r  rŠ  )r[  r\  Útrue)r  r‹  r3  r#   r  )r:  s   &r   Ú_sudo_noninteractive_okr=  Œ  st   € ðÜ�>Š>Ò0ÀÈqÐX]Ô^×iÑiÐmnÔnÙä�~Š~˜v tÐ=¨nÐ=ÈdÐ\]ÐejÔk×vÑvÐz{Ñ{Ð{øÜ”Z×.Ñ.Ð/ô Úðús   ‚+A ¯*A ÁA9Á8A9c                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r   ÚcacheÚscope_Ú
scope_cmd_Ú	svc_name_)r2   r0   r1   )r   s   "r   r   r   �  s(   € ÷ ñ œtð ¬Sð ¼dð Ìsñ r   c                ó²   € W9   d	   W,          # VR.,           p\        V4      '       d*   RR.V,           p\        VRV.,           4      '       d   TMRpW@V&   V# )u?  Resolve the command prefix for manage-units verbs (None â‡’ no privilege path).

Manage-units verbs on a *system* service trigger a polkit prompt for non-root
users, which flashes and dies inside our captured 10-15s subprocess. Root â†’ plain
systemctl; else ``sudo -n`` blanket probe, then a targeted ``reset-failed`` probe
so a least-privilege sudoers entry scoped to hermes-gateway* qualifies (idempotent
no-op we run before every privileged restart anyway). On None the caller must SKIP
the restart (without draining first!). ``--no-ask-password`` prevents polkit hangs.
rZ  r[  r\  r�  N)r'  r=  )r?  r@  rA  rB  r‚  Úsudo_cmds   &&&&  r   Ú_resolve_manage_cmdrE  �  s`   € ð „Ø�}ÐØ
Ð+Ð,Õ
,€CÜ�6×ÒØ˜D�> CÕ'ˆÜ1°#¸ÈÐ8SÕ2S×TÒT‰hÐZ^ˆØˆ&�MØ€Jr   c                ó4   € V ^8„  d   QhR\         R\         RR/# )r   r*  r  r   Nr@   )r   s   "r   r   r   ±  s!   € ÷ !ñ !´3ð !¼sð !Àtñ !r   c                óø  € ^ RI HpHpHpHpHp VR8H  pV'       d   TMV! 4       V  R2,          p \        P                  ! RV R2VP                  RR7      \        P                  4      p	T	'       d   R# T'       d‚   \        T4      '       gq   Y! 4       8X  df   \        P                  P                  R	4      p
 T! R
R7       T
f#   \        P                  P                  R	R4       R# T
\        P                  R	&    R# \!        RT  RT RT RT'       d   RMR RT'       d   RMR 2
4       R#   \         d     R# i ; i  T
f"   \        P                  P                  R	R4       i T
\        P                  R	&   i ; i)al  A unit whose restart policy predates ``RestartPreventExitStatus=78`` crash-loops on the PERMANENT
exit: a ``Restart=on-failure`` system unit restarted ~180x on a host-attach refusal while the
regenerated user units parked (#118282). The gateway rewrites its USER unit at boot; a SYSTEM unit
lives in /etc, so rewrite it here when we are root, else name the repair.)Ú_SYSTEM_UNIT_DIRÚGATEWAY_FATAL_CONFIG_EXIT_CODEÚget_service_nameÚrefresh_systemd_unit_if_neededÚuser_systemd_unit_dirr   r²  z^RestartPreventExitStatus=.*\bz\brY   rZ   NÚHERMES_HOMET)r   r/  z  lacks RestartPreventExitStatus=z: a permanent refusal (exit z6) would crash-loop it instead of parking.
    Repair: úsudo r,   zhermes gateway installz	 --system)rÆ  rH  rI  rJ  rK  rL  ÚreÚsearchr]   Ú	MULTILINEr#   r'  r&  Úenvironrq   Úpopr  )r*  r  rH  rI  rJ  rK  rL  r   Ú	unit_pathÚparkedÚlaunch_homes   &&         r   Ú$_repair_unit_without_fatal_exit_parkrW  ±  sz  € ÷
õ ð �hÑ€Fß%+Ñ!Ñ1FÓ1HÈxÈjÐX`ÐLaÕa€IðÜ—’Ð<Ð=[Ð<\Ð\^Ð_Ðaj×atÑatð  JÐató  bKô  MO÷  MYñ  MYó  Zˆ÷ Ùß”k %×(Ò(¨XÐ9IÓ9KÔ-Kô —j‘j—n‘n ]Ó3ˆð	8Ù*°$Õ7àÒ"Ü—
‘
—‘˜}¨dÔ3ñ 	ð -8”—
‘
˜=Ò)ÙÜ	Ø
��
Ð:Ð;YÐ:Zð [Ø/Ð0ð 1ß"(‘w¨bÐ1Ð1G×W]ÉÐceÐGfð	höøô! ô Úðûð Ò"Ü—
‘
—‘˜}¨dÕ3à,7”—
‘
˜=Ò)ús   °:D- Â8	D? Ä-D<Ä;D<Ä?:E9c                óŠ   € V ^8„  d   QhR\         R\         R\        R\        R\        R\        R\        R\        R	,          R
R	/	# )r   r*  r  r  râ  Ú_manage_cmd_cacherà  rá  rË  Nr   )r0   r1   rƒ  r2   rŸ   )r   s   "r   r   r   Õ  sg   € ÷ iñ iÜðiÜ ðiÜ-1ðiÜAFðiÜ[_ðiäðiä59ðiäQTÐW[ÕQ[ðið 
ñir   c               óp  € \        VRV .,           ^R7      pVP                  P                  4       R8w  d   R# \        W 4      '       g   R# \	        W4       \        WAW 4      p	^ p
\        V 4      '       dQ    \        VRV RR.,           ^R7      p\        VP                  ;'       g    RP                  4       ;'       g    ^ 4      p
V
^ 8„  ;'       d    \        W£WR	7      pV'       dÝ   ^ R
IHpHp V	e[   \        V	RV .,           ^
R7       \        V	RV .,           V! W RR7      R7       \!        W RR7      '       d   VP#                  V 4       R# V! W RR7      pV	f#   VR8”  d   \%        RV  R\        V4       R24       \!        W \'        RVR,           4      R7      '       d   VP#                  V 4       R# \%        RV  R24       V	f&   VP#                  V 4       \%        RV  RV  R24       R# \)        W�VR7      pVP*                  ^ 8w  d=   VP#                  V 4       \%        RV  RVP,                  P                  4        24       R# \!        W RR7      '       d   VP#                  V 4       R# \%        RV  R24       \)        W�VR7       \!        W RR7      '       d#   VP#                  V 4       \%        RV  R24       R# VP#                  V 4       VR 8X  d   R!MRpVR"8X  d   R#MRp\%        R$V  R%V R&V R'V  R(V R)V R*V  R+V R)V R,V  24       R#   \        \        P                  \        3 d    ^ p
 ELoi ; i)-z¸Restart one active systemd gateway/serve unit: graceful SIGUSR1 drain, then forced restart.

Appends settled names to ``restarted_services`` and failures to ``failed_or_stale_units``.
ú	is-activer  ÚactiveNr0  r1  r2  r,   ©rË  )Úservice_restart_secrŽ  r�  ÚstartT)Ú
start_onlyrü  g        )rD   ç      @rñ  z%: waiting for systemd auto-restart (~z's; no root for an immediate restart)...r/  u0    drained but didn't relaunch â€” forcing restartz� is a system service and restarting it needs root.
    Restart it manually to load the new version:
      sudo systemctl restart zz
    To let `hermes update` restart it automatically, allow
    passwordless sudo for systemctl, or run updates with sudo.r]  rþ  rÔ  z  died after restart, retrying...u     âœ“ z recovered on retryr   z--user r   rN  rÖ  z7 failed to stay running after restart.
    Check logs: zjournalctl z-u z1 --since '2 min ago'
    Recover manually:
      z
systemctl zreset-failed z
      zrestart )r  r  rØ   rd  rW  rE  r¹  r,  rÖ   r  r  r  r1  r‘  r^  rŽ  rf  rM  r  Úmaxre  r3  r  )r*  r  r  râ  rY  rà  rá  rË  rŠ  Ú_manage_cmdÚ	_main_pidÚ_showÚ_graceful_okr^  rŽ  Ú_restart_secr�  Ú_scope_flagÚ
_sudo_hints   &$$$$$$$           r   Ú!_restart_one_systemd_gateway_unitrj  Õ  sd  € ô �y K°Ð#:Õ:ÀAÔF€EØ‡|�|×ÑÓ˜xÔ'ÙÜ(¨×=Ò=ÙÜ(¨Ô9ô &Ð&7À	ÓT€Kð €IÜ6°x×@Ò@ð	Ü˜y¨F°HÐ>RÐT]Ð+^Õ^ÐhiÔjˆEÜ˜UŸ\™\×/Ð/¨R×6Ñ6Ó8×=Ð=¸AÓ>ˆIð
 ˜q‘=÷ Vð VÔ%HØ ô&V€L÷ ßhð
 Ò"Ü�{ n°hÐ%?Õ?ÈÕLÜØ˜w¨Ð1Õ1Ù/°	ÐPTÔUõô (¨	ÀT×JÓJØ"×)Ñ)¨(Ô3Ùñ +¨9ÈÔLˆØÒ <°#Ô#5ÜØ˜˜
ð #"Ü"% lÓ"3Ð!4ð 57ð7ôô
 $ IÄÀTÈ<ÐZ^ÕK^ÓA_×`Ó`Ø×%Ñ% hÔ/Ùô 	��x�jÐ PÐQÔRð ÒØ×$Ñ$ XÔ.ÜØ�X�Jð ,à,4¨:ð 6MðNô	
ñ 	ô +¨;ÈIÔV€GØ×Ñ˜QÔØ×$Ñ$ XÔ.ÜÐ(¨¨
°"°W·^±^×5IÑ5IÓ5KÐ4LÐMÔNÙä 	¸T×BÓBØ×!Ñ! (Ô+Ùô 
ˆF�8�*Ð<Ð
=Ô>Ü  À)ÕLÜ 	¸T×BÓBØ×!Ñ! (Ô+Ü��x�jÐ 3Ð4Ô5ÙØ× Ñ  Ô*Ø$¨œ‘)°B€KØ! XÔ-‘°2€JÜ	Ø
��
ð Ø%˜, k°+°¸cÀ(Àð Là�˜J { m°=ÀÀ
ð KØ�˜J { m°8¸H¸:ð		GöøôS œJ×5Ñ5Ô7HÐIô 	Ø‹Ið	ús   Á6/L Â&L Â>L Ì"L5Ì4L5c                ó–  aaa€ ^ RI HpHp V! 4       '       g   R# / p\        \        4      ;_uu_ 4        V! 4        RRR4       R R lpR V3R llp	^ RIHp
 / o\        V4       F&  w  or¼\        VP                  SV3V3R llV	R	7       K(  	  \        S4      p/ p\        V4      ^8”  d   V
! VV3R
 l4      w  rÞVP                  4        F  w  pp\        RV RV R24       K  	  ^ RIHp V Fs  pSV,          w  oppVV! 4       R,          9   d   VP!                  V4       K6  \        V 4      p \#        VSVVVV SVR7       VP)                  V3R lV VR  4       4       Ku  	  R#   + '       g   i     EL6; i  \$        P&                   d   pT	! TT4        Rp?L[Rp?ii ; i  TP)                  T3R lT TR  4       4       i ; i)u÷   Restart every active hermes-gateway*/hermes-serve* systemd unit (user + system).

Settled units â†’ ``restarted_services`` (bare) and ``restarted_scoped_units``
(``scope/name``); failures â†’ ``failed_or_stale_units``. Per-unit timeouts isolated.
)Úsupports_systemd_servicesÚ_ensure_user_systemd_envNc                óH   € V ^8„  d   QhR\         R\        P                  RR/# )r   r  rÌ   r   N©r0   r  r  )r   s   "r   r   Ú4_restart_systemd_gateway_units.<locals>.__annotate__P  s'   € ÷ 
ñ 
¤ð 
¬*×*CÑ*Cð 
Èñ 
r   c                 óf   € \        R T  RVP                  '       d   VP                  MR R24       R# )u"     âš  systemctl timed out listing z-scope gateway units (úunknown commandz0). Check the gateway with: hermes gateway statusN)r  r‚  )r  rÌ   s   &&r   Ú_on_list_timeoutÚ8_restart_systemd_gateway_units.<locals>._on_list_timeoutP  s6   € äØ0°°ð 8Ø),¯¯¨˜cŸgšgÐ6GÐHð I<ð=ö	
r   c                óH   € V ^8„  d   QhR\         R\        P                  RR/# )r   r*  rÌ   r   Nro  )r   s   "r   r   rp  X  s'   € ÷ 	
ñ 	
¤3ð 	
¬Z×-FÑ-Fð 	
È4ñ 	
r   c                 óŠ   <€ SP                  V 4       \        R T  RVP                  '       d   VP                  MR R24       R# )u%     âš  systemctl timed out restarting z (rr  z%); continuing with remaining gatewaysN)rM  r  r‚  )r*  rÌ   rá  s   &&€r   Ú_on_unit_timeoutÚ8_restart_systemd_gateway_units.<locals>._on_unit_timeoutX  sF   ø€ ð 	×$Ñ$ XÔ.Üà3°H°:ð >ØŸ7Ÿ7˜7�—’Ð(9Ð:ð ;1ð2ö	
r   r=  c                 ó6   <€ SP                  V R V  2WV 34      # rA  rC  rE  s   &&&€r   rI  Ú0_restart_systemd_gateway_units.<locals>.<lambda>l  rK  r   rN  c                 óT   <€ \        SV ,          ^,          SV ,          ^,          4      # rR  rT  rU  s   &€r   rI  rz  u  rV  r   rW  rX  rY  rë  Úunits)r  r  râ  rY  rà  rá  rË  c              3   ó2   <"  € T F  pS R V 2x € K  	  R# 5i)rB  NrI   )r“   rÂ  r  s   & €r   r•   Ú1_restart_systemd_gateway_units.<locals>.<genexpr>“  s   øé € Ð)iÑHhÀ¨U¨G°1°T°FÕ*;ÓHhùs   ƒ)rÆ  rl  rm  r   rF   r8   r>  r!  rb  r  r1   rï   rc  r  rÿ  rì  rµ   rj  r  r  rÁ   )rà  rá  Úrestarted_scoped_unitsrâ  rË  rl  rm  rY  rs  rw  r>  r  r   rh  rÂ   ri  rj  rì  re   r*  Ú_scope_markrÌ   r  rH  s   &f&&&                 @@r   Ú_restart_systemd_gateway_unitsr�  A  sÈ  ú€ ÷ WÙ$×&Ò&ÙØ ÐÜ	”)×	Õ	Ù Ô"÷ 
õ
÷	
ð 	
õ SØ02€GÜ$BÐCSÖ$TÑ ˆˆyÜ&Ø�M‰MØ16¸Yö Bà,÷		
ñ %Uô �‹=€DØ €GÜ
ˆ4ƒy�1„}á8ØÔNóP‰ˆà&Ÿ}™}žÑˆ�)ÜØ�X�JÐbØˆkð 4ð4ö	
ñ  /õ DÛˆØ%,¨S¥\Ñ"ˆˆy˜(ØÑ#Ó% gÕ.Ô.Ø"×&Ñ& sÔ+ÙäÐ,Ó-ˆð	jÜ-ØØØ#Ø)Ø"3Ø#5Ø&;Ø%9õ	ð #×)Ñ)Ô)iÐHZÐ[fÐ[gÑHhÓ)iÖió+ ÷c 
×	Ð	ûôF ×(Ñ(ô 	,Ù˜X s×+Ñ+ûð	,ûð #×)Ñ)Ô)iÐHZÐ[fÐ[gÑHhÓ)iÕiús5   ´E)Ä2E=Å)E:	Å=F%Æ	F ÆF(Æ F%Æ%F(Æ( Gc                ó<   € V ^8„  d   QhR\         R\        R\        /# r)  r+  )r   s   "r   r   r   –  r-  r   c                óH  €  \        \        V 4      RVRR.,           ^
R7      p\        TR^4      ^ 8w  d   ^ #  \        \        TRR4      ;'       g    RP                  4       ;'       g    ^ 4      #   \        \        P                  3 d     ^ # i ; i  \         d     ^ # i ; ir/  r4  r6  s   && r   r7  r7  –  r8  r9  c                   óŠ   a € ] tR tRt o Rt]! ]R7      t]! ]R7      t]! ]R7      t	V 3R lR lt
V 3R lR ltV 3R ltR	tV tR
# )Ú_GatewayRestartOutcomei¨  u¡   Restart-phase bookkeeping. ``restarted_services`` keeps bare unit names (fleet
probe, receipt, summary read it); ``incomplete`` â‡’ a gateway may still be stale.)Údefault_factoryc                ó    <€ V ^8„  d   QhRS[ /# r'   )r    )r   Ú__classdict__s   "€r   r   Ú#_GatewayRestartOutcome.__annotate__Á  s   ø€ ÷ Bñ B¡Uñ Br   c                ó®   € V P                   pVe$   V Uu. uF  q"V P                  9  g   K  VNK  	  ppWP                  V P                  ,
          3# u upi )u�   ``(pre_restart_pids, killed_pids)`` with the unmapped stops removed â€” the signals that
legitimately predict a fleet-matrix row.)Úpre_restart_gateway_pidsÚstopped_unmapped_pidsÚkilled_pids)ÚselfÚprerŸ  s   &  r   Úfleet_probe_signalsÚ*_GatewayRestartOutcome.fleet_probe_signalsÁ  sU   € ð ×+Ñ+ˆØŠ?Ù"%ÓO¡#˜3°D×4NÑ4NÑ)N—3�3¡#ˆCÐOØ×$Ñ$ t×'AÑ'AÕAÐAÐAùò Ps
   •A¬Ac                ó   <€ V ^8„  d   QhRR/# rH   rI   )r   rˆ  s   "€r   r   r‰  É  s   ø€ ÷ 	ñ 	¨ñ 	r   c                ó,  € \        \        4      ;_uu_ 4        ^ RIHp V! R	RV P                  RV P
                  RV P                  R\        V P                  4      RV P                  RV P                  /VB  RRR4       R#   + '       g   i     R# ; i)
zDBest-effort ``record_gateway_restart`` from the current bookkeeping.)Úrecord_gateway_restartrà  Úrelaunched_profilesÚexternally_supervised_profilesr�  r»  rz   NrI   )r   rF   r!   r”  rà  r•  r–  Úsortedr�  rá  rz   )rŽ  Úextrar”  s   &, r   Úrecord_receiptÚ%_GatewayRestartOutcome.record_receiptÉ  s�   € ä”i× Õ ÝHÙ"ñ Ø#'×#:Ñ#:ðØPT×PhÑPhðà/3×/RÑ/Rðô # 4×#3Ñ#3Ó4ðð DH×C]ÑC]ðð  Ÿ?™?ð	ð /4ò	÷ !× × Ò ús   ˜A BÂB	c                ó¬   <€ V ^8„  d   Qh/ S[ ;R&   S[;R&   S[R,          ;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R	&   S[;R
&   S[;R&   S[;R&   # )r   rz   Úphase_errorsNr‹  rà  rá  r•  r–  r�  rŒ  r  Úself_restart_pending_pids)r   r1   rŸ   )r   rˆ  s   "€r   r   r‰  ¨  s˜   ø‡ ‚ ñ
 Ññ ñ Ññ ñ # T�kÑ)ñ ñ Ññ ñ  Ññ ñ Ññ ñ %)Ñ(ñ ñ Ññ ñ  Ñ;ñ! ñ&  Ñ<ñ' ñ.  #Ñ?ò/ r   rI   N)rÚ  Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   rŸ   rŒ  r  r�  r�  r™  Ú__annotate_func__Ú__static_attributes__Ú__classdictcell__)rˆ  s   @r   r…  r…  ¨  sP   ø‡ € ñZñ "'°sÔ!;Ðñ #(¸Ô"<Ðñ &+¸3Ô%?Ð÷Bð B÷	ð 	÷C ƒ r   r…  c                ó(   € V ^8„  d   QhR\         RR/# ©r   Úoutr   N©r…  )r   s   "r   r   r   Õ  s#   € ÷ PUñ PUÔ"8ð PUÈDñ PUr   c                ó¶  € ^ RI p^ RIHpHpHpHpHp ^ RIHp V! RR7      V! 4       R,          ,          p	V! V	RR7      p
V! V	R7       Uu/ uF#  pVP                  V
9   g   K  VP                  VbK%  	  pp\        W¬R	7      p
\        4       pVP                  4        EF2  w  rëV! VP                  V4      pVf0   \        R
VP                   RV R24       VP                  V4       KL  \!        WáVP                  V P"                  R7      '       gF   \%        \&        \(        4      ;_uu_ 4        \*        P,                  ! WâP.                  4       RRR4       V! RRR7       V P0                  P                  V4       VR8X  d)   V P2                  P5                  VP                  4       EK  V P6                  P5                  VP                  4       EK5  	  V
 FŒ  pWì9   d	   Wí9  d   K  \%        \&        \(        4      ;_uu_ 4        \*        P,                  ! WâP.                  4       V P0                  P                  V4       V P8                  P                  V4       RRR4       KŽ  	  V P:                  '       g   V P0                  '       Ed#   \        4        V P:                   F  p\        RV 24       K  	  V P6                  '       d(   \        RRP=                  V P6                  4       24       V P2                  '       d*   RP=                  V P2                  4      p\        RV 24       \?        V P0                  4      \?        V P6                  4      ,
          \?        V P2                  4      ,
          pV'       d1   \        RV R24       \        R4       V^8”  d   \        R4       R# R# R# R# u upi   + '       g   i     ELo; i  + '       g   i     EK  ; i)z•Drain/stop every manual (non-service) gateway and print the restart summary.

Mutates ``out`` in place; raises so the caller's abort recovery fires.
N)r  Úfind_profile_gateway_processesÚ'_prepare_profile_gateway_update_restartÚ_get_service_pidsÚ_wait_for_gateway_exitrë  Tr  rž  ©Úexclude_pidsr  )r¯  )r™  r/  z5: could not arm an automatic gateway restart for PID uB    â€” stopping it instead so it cannot keep running pre-update coder]  ra  )r  Úforce_afterzexternal-supervisoru     âœ“ Restarted u,     âœ“ Restarting manual gateway profile(s): rï  uC     âœ“ Handed gateway profile(s) back to their external supervisor: u     â†’ Stopped z manual gateway process(es)z(    Restart manually: hermes gateway runz;    (or: hermes -p <profile> gateway run  for each profile)) ÚsignalrÆ  r  rª  r«  r¬  r­  rÿ  rì  rŸ  r¢  rŸ   rc  r7   r  rµ   r1  r�  r   ÚProcessLookupErrorÚPermissionErrorr&  ÚkillÚSIGTERMr�  r–  rM  r•  rŒ  rà  r   rï   )r§  Ú_drain_budgetÚ_signalr  rª  r«  r¬  r­  rì  Úservice_pidsÚmanual_pidsÚprocÚprofile_processesÚunrestartable_pidsrŸ  Úrestart_modeÚsvcÚnamesÚunmapped_counts   &&                 r   Ú_restart_manual_gatewaysrÁ  Õ  s  € ó
 ÷õ õ
 Dá$°$Ô7Ñ:KÓ:MÈfÕ:UÕU€LÙ#°ÈDÔQ€Kñ 3ÀÕMóáMˆDØ�8‰8�{Ñ"ô 	ˆ�‰�$ŠÙMð ð ô .¨kÔR€Kô ›ÐØ&×,Ñ,×.‰	ˆÙ>¸t¿|¹|ÈSÓQˆØÒäØ˜Ÿ™˜ð '+Ø+.¨%ð 0<ð<ôð
 ×"Ñ" 3Ô'Ùô 3Ø D§L¡LÀs×GdÑGd÷fó fäÔ,¬o×>Õ>Ü—’˜Ÿ_™_Ô-÷ ?ñ
 	 s¸Õ=Ø�‰×Ñ˜CÔ ØÐ0Ô0Ø×.Ñ.×5Ñ5°d·l±l×Cà×#Ñ#×*Ñ*¨4¯<©<×8ñ5 /ó8 ˆØÔ#¨Ô(EÙÜÔ(¬/×:Õ:Ü�GŠG�CŸ™Ô)Ø�O‰O×Ñ Ô$Ø×%Ñ%×)Ñ)¨#Ô.÷ ;Ñ:ñ ð ××Ð §§¡ÜŒØ×)Ô)ˆCÜÐ$ S EÐ*Ö+ñ *à×"×"Ð"ÜÐ@ÀÇÁÈ3×KbÑKbÓAcÐ@dÐeÔfØ×-×-Ð-Ø—I‘I˜c×@Ñ@ÓAˆEÜÐWÐX]ÐW^Ð_Ô`Ü˜cŸo™oÓ.´°S×5LÑ5LÓ1MÕMÔPSÐTW×TvÑTvÓPwÕwˆßÜ�N >Ð"2Ð2MÐNÔOÜÐ<Ô=Ø Ô!ÜÐSÖTñ "ñ ñ "1ùòg÷> ?×>Ð>ú÷ ;×:Ñ:ús%   Á
N-Á"N-Ä+!N2ÈAOÎ2OÏOc                ó   € V ^8„  d   QhRR/# rH   rI   )r   s   "r   r   r   (  s   € ÷ ñ ¨tñ r   c                ó@  € \        R4      ;_uu_ 4        ^ RIHpHp \        P
                  ! R4       V! V! RR7      RR7      pV Uu. uF  qDV 9   g   K  VNK  	  ppV'       d…   \        4        \        R\        V4       R24       ^ R	IH	pH
p V F>  p\        \        \        \        4      ;_uu_ 4        V! VRV! V4      R
7       RRR4       K@  	  \        P
                  ! R4       RRR4       R# u upi   + '       g   i     Kx  ; i  + '       g   i     R# ; i)zÖSurvivor sweep: gateways ignoring SIGTERM (stuck drain, blocked I/O, zombie) never
exit, so the watcher never respawns and ImportErrors persist. Give graceful paths a
moment, then SIGKILL remaining pre-update PIDs.z&Post-restart survivor sweep failed: %s)r  r¬  g      @Tr  r®  r/  u6    gateway process(es) ignored SIGTERM â€” force-killing)Úget_process_start_timeÚterminate_pid)ÚforceÚexpected_start_timeNg      ø?)r   rÆ  r  r¬  Ú_timeÚsleepr  rï   r6  rÄ  rÅ  r   r²  r³  r#   )r�  r  r¬  Ú
_survivingrŸ  Ú_stuckrÄ  rÅ  s   &       r   Ú_force_kill_stuck_gatewaysrÌ  (  sÞ   € ô 
Ð>×	?Õ	?ßKô
 	�Š�CÔÙ&Ñ4EÐSWÔ4XÐgkÔlˆ
á!+ÓB¡˜#°kÑ/A—#�#¡ˆÐBßÜŒGÜ�Fœ3˜v›;˜-Ð']Ð^Ô_ßLÛ�ÜÔ0´/Ä7×KÕKá! #¨TÑG]Ð^aÓGbÕc÷ LÑKñ ô
 �KŠK˜Ô÷' 
@Ñ	?ùò C÷ L×KÐKú÷ 
@×	?Ð	?ús<   ”4DÁC3ÁC3ÁADÂ5C8Ã"DÃ3DÃ8D	Ä	DÄD	c                ó(   € V ^8„  d   QhR\         RR/# r¦  r¨  )r   s   "r   r   r   B  s$   € ÷ GLñ GLÜ4ðGLà	ñGLr   c          
     ó¢  a€ ^ RI Hp ^ RIHpHpHpHp	 \        P                  RV 4       SP                  P                  \        V 4      4       \        4       p
\        VRR4      ;'       g    R Uu0 uFF  p\        VRR4      R8X  g   K  \        \        VRR4      \        4      '       g   K:  VP                  kKH  	  pp\!        SP"                  4      \!        SP$                  4      ,          pVP'                  V3R	 lV 4       4       V! WV\!        V4      R
7      p\)        VP+                  R4      ;'       g    / P+                  R4      ;'       g    . 4      pV! V4      pVVR&   \!        VP+                  R4      ;'       g    . 4      pSP"                  P-                  V3R l\/        V4       4       4       V! VVV,          VVR7      '       d   RSn        V	! V4       ML\3        V
SP4                  4      '       g   V! V4      '       g	   V'       d   RSn        \7        W
4       V	! V4       SP9                  \        V 4      VR7       R# u upi )zZPhase-abort recovery: fresh-child restart + fail-closed verdict; updates ``out`` in place.)Ú_owed_stale_serve_rows)Ú_abort_recovery_is_completeÚ$_recover_gateway_restart_after_abortÚ$_surviving_pre_update_serve_runtimesÚ_warn_stale_serve_runtimesz(Gateway restart during update failed: %sr-   r­   Nr¬   r7   c              3   óÖ   <a"  € T F]  o\         ;QJ d)    V3R  lSP                   4       F  '       g   K   RM	  RM! V3R  lSP                   4       4      '       g   KY  Sx € K_  	  R# 5i)c              3   ó<   <"  € T F  p\        SV4      x € K  	  R # 5ir‰   r	   )r“   Úservicer7   s   & €r   r•   Ú?_recover_after_restart_phase_abort.<locals>.<genexpr>.<genexpr>a  s   øé € ÐhÑQgÀgÔ/°¸×AÐAÓQgùs   ƒTFN)rš   rà  ©r“   r7   r§  s   &@€r   r•   Ú5_recover_after_restart_phase_abort.<locals>.<genexpr>^  sF   ùé € ð 'á0ˆGß‹3ÔhÐQT×QgÒQgÓh�3�3Š3ÔhÐQT×QgÒQgÓh×h÷ 	ŠÛ0ùs   „A)”A)µ%A)Á
A))Úgateway_moder  Ú
skip_unitsÚserve_unitsr}   Ústale_runtimesÚverifiedc              3   óL   <"  € T F  qSP                   9  g   K  Vx € K  	  R # 5ir‰   )r•  rØ  s   & €r   r•   rÙ  r  s"   øé € ð #Ù9�GÈC×LcÑLcÑ=c�ŠÓ9ùs   ƒ$š
$)Úplanned_gateway_profilesÚcovered_gateway_profilesÚrecovery_resultÚstale_runtime_rowsFT)rô   Úfresh_recoveryrI   )Ú hermes_cli.update_abort_recoveryrÏ  r    rÐ  rÑ  rÒ  rÓ  r;   r<   rœ  rM  r0   r  r5  r€   r7   rŸ   r•  r–  rÁ   r1   rq   r³   r—  rz   Ú$_restart_phase_failure_is_incompleter‹  r(  r™  )rÜ  Ú_pre_update_planr§  rÚ  r  rÏ  rÐ  rÑ  rÒ  rÓ  rÊ  r™   Ú_planned_gateway_profilesÚ_already_restarted_profilesÚ_recovery_resultÚ_serve_units_failedÚ_stale_runtime_rowsÚ_recovery_verifieds   &&f$$             r   Ú"_recover_after_restart_phase_abortrî  B  s,  ø€ õ H÷ó ô ‡L�LÐ;¸QÔ?Ø×Ñ×ÑœC ›FÔ#ô >Ó?€Jô Ð/°¸RÓ@×FÐFÀBÐFó!áFˆGÜ�7˜F DÓ)¨YÑ6ô 	ô ”w˜w¨	°4Ó8¼#×>ô 	ˆ�ŒÙFð ð !ô #& c×&=Ñ&=Ó">ÄÀS×EgÑEgÓAhÕ"hÐØ×&Ñ&ô 'á0ó'ô ñ
 <ØÐC^ÜÐ-Ó.ôÐô Ð 0× 4Ñ 4°]Ó C× IÐ IÀr×NÑNÈxÓX×^Ð^Ð\^Ó_Ðñ ?Ð?OÓPÐØ)<ÐÐ%Ñ&ô Ð-×1Ñ1°*Ó=×CÐCÀÓDÐØ×Ñ×"Ñ"ô #Ü%Ð&8Ô9ó#ô ñ #Ø!:Ø!<Ð?QÕ!QØ(Ø.÷	ó ð ˆŒÙ"Ð#6Õ7ä,¨Z¸×9UÑ9U×VÒVÙ!Ð"5×6Ò6ßð ˆŒÜ+¨AÔ:Ù"Ð#6Ô7Ø×Ñ¤3 q£6Ð:JÐÖKùòe!s   Á1IÂ
IÂ-Ic                ó$   € V ^8„  d   QhR\         /# r'   )rƒ  )r   s   "r   r   r   Œ  s   € ÷ ñ œuñ r   c                 óh   €  ^ RI Hp  \        \        V ! 4       4      R4      #   \         d     R# i ; i)zRSeconds a drain-first (SIGUSR1) restart may wait for a gateway to exit; 45s floor.©Ú_get_restart_exit_wait_budgetg     €F@)rÆ  rò  rb  rƒ  rF   rñ  s    r   Ú_gateway_drain_budgetró  Œ  s2   € ðÝDÜ”5Ñ6Ó8Ó9¸4Ó@Ð@øÜô Úðús   ‚" ¢1°1c                ó$   € V ^8„  d   QhR\         /# )r   rÚ  r   )r   s   "r   r   r   •  s   € ÷ Sñ SÌñ Sr   c                ó¬  € ^ RI Hp \        R. . . . . . \        4       R7      p\        4       p ^ RIHpHpHpHpH	p	H
p
 \        4       p \        V! RR7      RR7      Vn        \        VP                   VP"                  WKVP$                  4       V! 4       '       dS   \'        \(        \*        4      ;_uu_ 4        \-        VP                   VP"                  VVP$                  R	7       RRR4       \/        W;4       VP"                  '       d   RVn        \3        VP"                  4       VP5                  4        \7        VP8                  4       \        V4      Vn        VP0                  '       g   ^ RIH p V! \C        4       4       V#   \         d    RTn         EL8i ; i  + '       g   i     LÁ; i  \         d   p\;        YÀY1TR
7        Rp?L„Rp?ii ; i)zËRestart every running gateway (systemd, launchd, manual) onto the pulled code.

Never raises: a phase abort runs fresh-child recovery and fails closed unless
every planned gateway is verifiably covered.
r4   F)rz   rœ  r‹  rà  rá  r•  r–  r�  )r½  r  rª  r«  r¬  r­  Tr  r  Nr]  )rÚ  r  )Úmark_host_restart_completed)"r    r5   r…  rŸ   rÆ  r½  r  rª  r«  r¬  r­  ró  r¢  r‹  rF   r�  rà  rá  r�  r   r  ÚImportErrorr  rÁ  rz   rÉ  r™  rÌ  r�  rî  r  r8   rö  rt  )rç  rÚ  r5   r§  r  r½  r  rª  r«  r¬  r­  r¶  rÜ  rö  s   &&            r   Ú#_restart_gateway_fleet_after_updaterø  •  s‹  € õ )ô
 !Ø rÀBÐ[]ÐuwØ¸rÌsËuô€Cô #&£%Ðð0
÷	
÷ 	
ô .Ó/ˆð	0Ü+FÑGXÐfjÔGkÐswÔ+xˆCÔ(ô 	'Ø×"Ñ" C×$=Ñ$=Ð?UØ×)Ñ)ô	
ñ �:Š:ÜÔ+¬[×9Õ9Ü/Ø×*Ñ*¨C×,EÑ,EÀ}Ø),×)FÑ)Fõ÷ :ô 	! Ô4à×$×$Ð$à!ˆCŒNÜ.¨s×/HÑ/HÔIØ×ÑÔÜ" 3§?¡?Ô3ô "%Ð%;Ó!<€CÔØ�>�>ˆ>õ 	RÙ#Ô$9Ó$;Ô<Ø€JøôI ô 	0Ø+/ˆC×(ð	0ú÷ :×9ûô ô 
Ü*Ø ÐXn÷	
ò 	
ûð
úsU   ­F0 ÁF Á!AF0 Â6.FÃ$A&F0 ÆFÆF0 ÆFÆF0 ÆF-	Æ(F0 Æ0GÆ;GÇGc                ó$   € V ^8„  d   QhR\         /# r'   r   )r   s   "r   r   r   ë  s   € ÷ >ñ >Ìñ >r   c                óL   € V e	   V '       d   R# VRJ ;'       g    \        V4      # )u	  Whether an escaped restart-phase exception must fail the update.

Fail closed unless provably safe: ``surviving`` None (unprobeable) or non-empty â†’
stale. ``[]`` proves safety ONLY if nothing ran beforehand; a pre-restart gateway
(``pre_restart_pids`` non-empty or None) now gone was stopped unverified.

* ``surviving is None`` â€” the survivor probe could not determine state (typically the freshly-pulled
``hermes_cli.gateway`` no longer imports, one of the ways the phase aborts). That is proof-of-safety
ONLY when nothing was running before we touched anything. If a gateway was discovered pre-restart
(``pre_restart_pids`` non-empty, or ``None`` meaning the pre-state could not be read), it was stopped
without a verified replacement, so we still fail closed (#78574).
NTr   )Ú	survivingÚpre_restart_pidss   &&r   ræ  ræ  ë  s(   € ð ÒŸIÙØ˜tÐ#×=Ð=¤tÐ,<Ó'=Ð=r   c                ó$   € V ^8„  d   QhR\         /# r'   r   )r   s   "r   r   r   ý  s   € ÷ !ñ !ä	ñ!r   c                ój  € ?V'       g	   V'       d   R# Ve	   V'       d   R# \        \        4      ;_uu_ 4        V eZ   \        ;QJ d&    R V P                   4       F  '       g   K   RM	  RM! R V P                   4       4      '       d    RRR4       R# RRR4       R#   + '       g   i     R# ; i)u»  Whether the post-update fleet probe should have produced rows.

``collect_fleet_versions()`` swallows every failure and an empty matrix prints as
healthy, so zero rows is only proof-of-safety when NOTHING says a gateway existed
pre-update. Signals: ``restarted_services``/``killed_pids``; ``pre_restart_pids``
non-empty or None (same contract as ``_restart_phase_failure_is_incomplete``); plan
inventoried â‰¥1 ``kind == "gateway"`` runtime. ``windows_resume_token`` is deliberately EXCLUDED: it is
pause/resume bookkeeping, not an inventory, and its entries don't map to probe rows
(``unmapped`` Scheduled-Task gateways never publish gateway_state.json; a paused
profile resumes DETACHED). Counting it made every Windows update that paused a
gateway exit 1 after a long silent wait; a live pre-update Windows gateway is already
covered by ``pre_restart_pids`` and the plan. The same condition gates the settle sleep.

See #93406.
See #78574.
See #93406.
TNc              3   óB   "  € T F  p\        VR R4      R8H  x € K  	  R# 5i)r­   Nr¬   )r5  )r“   r™   s   & r   r•   Ú1_fleet_probe_expected_runtimes.<locals>.<genexpr>  s"   é € ð /
ÙG_¸GŒG�G˜V TÓ*¨iÖ7ÓG_ùrÅ  F)r   rF   rš   r-   )Úpre_update_planrü  Úwindows_resume_tokenrà  r�  s   &&&&&r   Ú_fleet_probe_expected_runtimesr  ý  s‹   € ð( 	çŸ[ÙØÒ×#3ÙÜ	”)×	Õ	ð Ò&¯3«3ñ /
ØGV×G_ÒG_ó/
¯3¯3ª3ñ /
ØGV×G_ÒG_ó/
÷ ,
ò ,
ð ÷ 
×	Ñ	ñ ÷ 
Ö	ñ ús   ¹B!Á	B!Á'$B!ÂB!Â!B2	c                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r   rA  rB  r  r   )r1   r0   rƒ  r   )r   s   "r   r   r   !  s)   € ÷ ñ ¬ð ¼#ð Ìð ÔY]ñ r   c                ó¾  € \         P                  ! 4       \        VR4      ,           p \        \        \
        P                  4      ;_uu_ 4        \        V RV.,           ^R7      pVP                  P                  4       R8X  d    RRR4       R#  RRR4       \         P                  ! 4       V8¼  d   R# \         P                  ! R4       K¥    + '       g   i     LD; i)z—Poll ``systemctl is-active`` (0.5s) up to ``timeout``: the Stopped -> Started
transition isn't instantaneous, so a one-shot check falsely reports down.g      à?Tr[  r  r\  NF)rÈ  Ú	monotonicrb  r   r  r  r  r  r  rØ   rÉ  )rA  rB  r  ÚdeadlineÚ_verifys   &&&  r   rf  rf  !  sž   € ô �ŠÓ ¤3 w°Ó#4Õ4€HØ
ÜÔ'¬×)BÑ)B×CÕCÜ  ¨{¸IÐ.FÕ!FÐPQÔRˆGØ�~‰~×#Ñ#Ó%¨Ô1Ø÷ DÑCà1÷ Dô �?Š?Ó Ô(ÙÜ�Š�CÖ÷ D×Cús   Á7CÃC	>   Ús6r  rÖ  Úsystemd)z
list-unitszhermes-gateway*zhermes-serve*zhermes-dashboard*z--plainz--no-legendz
--no-pagerr‰   >   Údesktopr  rÖ  r
  údesktop-sshrœ   úwindows-service)rë   )r¬   r,   rI   )rü  )_r¡  rì   ÚloggingrO  Ú
contextlibr   r&  r  r
  ÚtimerÈ  Údataclassesr   r   Úpathlibr   Úhermes_cli.update_cmd_commonr   r8   r   r  r
   Ú	getLoggerr;   r)   Ú	frozensetr  r  r  r%   r*   r>   r=   rN   rT   rh   rs   r‚   r›   r´   Ú _SUPERVISOR_OWNED_SERVE_BACKENDSrº   rÄ   rÍ   r×   rÙ   rå   rñ   r÷   r  r  r  r  r!  r'  r7  rl  rq  rt  rz  r€  r  re  rd  r¢  rª  r®  rb  r¹  rÉ  rÝ  r  r  r  r  r  r  r!  r(  r1  r  r=  rE  rW  rj  r�  r…  rÁ  rÌ  rî  ró  rø  ræ  r  rf  rI   r   r   Ú<module>r     sæ  ðñó Û Û 	Ý Û 	Û Û 
Û ß (Ý å 5Ý AÝ Hð 
×	Ò	Ð2Ó	3€ð 2Ð á&Ò'NÓOÐ à˜[¨(Ð3Ð4°xÀ+ÀÐ6OÐP€òÐ õ8õ;ðM¸rð MÐaeð MÐtv÷ Mõ*õaõõõ4=õ>÷*&ñR 'ÚbóÐ ð $>ÀÐ@PÕ#PÐ  õ(õBð ð  FR÷ ð6 $Ð õõ<õ*Võr/ðR¸Dð RÐfj÷ Rð&R¸ð RÐcg÷ Rð0Q°5÷ QõPô 'õ$õõ$4uõnõ(õ.õ0'õAð
KÐ^b÷ Kõð 	@¨bð 	@À÷ 	@õ
õ	õ+õ,
RõVð<KØ"&ðKØKO÷Kð\[gØotð[gà'+÷[gò|ð  fð ðKð ðð ðMð ð(È$÷ (õV'ð0*`ØUY÷*`õZ	õõ"õ(!ðHià^b÷iôXRjõjð$ ÷)ð )ó ð)õXPUõfõ4GLõTõSõl>õ$!÷Hñ r   