+
    jHàj"X  ã                  ó†  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIHtHtHt ^ RIHt RtR=t^Zt^t^ RIHt ]P0                  ! R4      t]P0                  ! R4      tR>tR?t^<t^
tR	tR
 R lt R R lt!R R lt"R R lt#R@R R llt$R R lt%R R lt&R R lt'R R lt(R R lt)R R lt*R RR!]PV                  /R" R# llt,R$ R% lt-R& R' lt.R( R) lt/R*R+/R, R- llt0R. R/ lt1R0 R1 lt2R2 R3 lt3R4RAR!]PV                  R5]
Ph                  /R6 R7 llt5R8 R9 lt6R@R: R; llt7]8R<8X  d   ]9! ]7! 4       4      hR# )Bu²	  Restart supervised gateway profiles from a clean Python generation.

The normal update command keeps executing in the interpreter that started before
``git pull``.  This module is deliberately small: it imports no gateway code
itself and launches the regular per-profile gateway command in a new
interpreter.  It is used only after the in-process restart phase has raised, so
that the recovery path cannot inherit the stale ``sys.modules`` graph that
caused the failure.

Outcome vocabulary (deliberately conservative):

- ``verified``          â€” the relaunch command exited 0 AND the profile's
  systemd unit was independently observed ``active`` afterwards.  This is the
  only outcome that may claim supervisor coverage.
- ``relaunch_attempted`` â€” the relaunch command exited 0 but no independent
  supervisor observation was possible (non-systemd supervisor, ``systemctl``
  missing, or the unit probe was inconclusive).  ``rc == 0`` from
  ``gateway restart`` is not proof that the new code generation is running,
  so this outcome must never be treated as verified coverage.
- ``failed``            â€” the relaunch command errored, timed out, or exited
  non-zero.

The pass covers two runtime families, because the in-process restart phase
covers both and an abort can strand either one (#92145):

- **gateway profiles**, relaunched through the existing per-profile
  ``hermes_cli.main -p <profile> gateway restart`` command; and
- **``hermes-serve*`` systemd units**, restarted directly through
  ``systemctl``.  ``hermes serve`` is not a gateway profile and has no
  per-profile relaunch command, but it is the runtime that hosts
  ``tui_gateway.server``: the process the original report saw answering every
  chat turn with an ``ImportError`` for a symbol that existed on disk.  The
  unit family is enumerated from systemd itself rather than from the update
  inventory, so a manually launched or Desktop-owned ``hermes serve`` â€” which
  has no relaunch authority â€” can never enter this path.

Serve-unit identity is always ``<scope>/<unit>`` (``user/hermes-serve``,
``system/hermes-serve``).  The two managers can each own a unit of the same
name and they are different processes: an identity that projects the scope
away lets one settled unit suppress recovery of the other, and lets one
scope's outcome speak for the other's.  Scope is therefore never dropped and
reconstructed â€” not in the skip payload, not in ``verified``/``failed``, not
in the receipt.
)ÚannotationsN)ÚCallableÚIterableÚMapping)ÚAnyÚHERMES_UPDATE_RESTART_RECOVERY)ÚPROFILE_ID_REz^[a-z0-9][a-z0-9_-]{0,31}$z?^hermes-(serve|dashboard)(-[a-z0-9][a-z0-9_-]{0,63})?\.service$g      ð?c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )é   ÚrunúCallable[..., Any]Úargvú	list[str]ÚtimeoutÚintÚextrar   Úreturnz
Any | None© )Úformats   "ÚG/home/ubuntu/.hermes/hermes-agent/hermes_cli/update_restart_recovery.pyÚ__annotate__r   J   s2   € ÷ ñ Ð&ð ¨ið ÀSð ÐSVð Ð[eñ ó    c               ór   €  V ! V3RRRRRRRRRR	R
V/VB #   \         \        P                  3 d     R# i ; i)zIRun ``argv`` capturing text output; ``None`` when it errors or times out.Úcapture_outputTÚtextÚencodingzutf-8ÚerrorsÚreplaceÚcheckFr   N)ÚOSErrorÚ
subprocessÚTimeoutExpired)r   r   r   r   s   &&$,r   Ú
_run_quietr"   J   sn   € ðÙØñ
Ø!%ð
Ø,0ð
Ø;Bð
ØKTð
àð
à!(ð
à,1ñ
ð 	
øô ”Z×.Ñ.Ð/ô Úðús   ‚ —6µ6c               ó    € V ^8„  d   QhRRRR/# )r
   Úresultr   r   Ústrr   )r   s   "r   r   r   U   s   € ÷ 9ñ 9�Cð 9˜Cñ 9r   c                óL   € \        V R R4      ;'       g    RP                  4       # )ÚstdoutÚ )ÚgetattrÚstrip©r$   s   &r   Ú_stdoutr,   U   s"   € Ü�F˜H bÓ)×/Ð/¨R×6Ñ6Ó8Ð8r   c               ó    € V ^8„  d   QhRRRR/# )r
   r$   r   r   Úboolr   )r   s   "r   r   r   Y   s   € ÷ Hñ H�sð H˜tñ Hr   c                ó:   € V R J;'       d    \        V R^4      ^ 8H  # )NÚ
returncode)r)   r+   s   &r   Ú
_succeededr1   Y   s#   € Ø˜Ð×GÐG¤'¨&°,ÀÓ"BÀaÑ"GÐGr   c               ó   € V ^8„  d   QhRR/# ©r
   r   r%   r   )r   s   "r   r   r   ]   s   € ÷ 	ñ 	˜ñ 	r   c                 óp  € \         P                  P                  RR4      P                  4       p V '       d€   \         P                  P                  V 4      p\         P                  P                  \         P                  P                  V4      4      R8X  d    \         P                  P                  V4      # R# )u  Profile this recovery process was launched as: ``<root>/profiles/<name>`` in ``HERMES_HOME`` names it,
anything else is the default profile. Mirrors ``hermes_cli.profiles.profile_root_for_env_home`` without
importing it â€” this module stays stdlib-only at import time.ÚHERMES_HOMEr(   ÚprofilesÚdefault)ÚosÚenvironÚgetr*   ÚpathÚnormpathÚbasenameÚdirname)Úhomer;   s     r   Ú_launch_profiler@   ]   st   € ô �:‰:�>‰>˜-¨Ó,×2Ñ2Ó4€DßÜ�w‰w×Ñ Ó%ˆÜ�7‰7×ÑœBŸG™GŸO™O¨DÓ1Ó2°jÔ@Ü—7‘7×#Ñ# DÓ)Ð)Ùr   c               ó    € V ^8„  d   QhRRRR/# )r
   Úprofilez
str | Noner   zdict[str, str]r   )r   s   "r   r   r   i   s   € ÷ ñ  
ð °nñ r   c                ó  € \        4       pV e   T MTpVR8X  d   VR8w  d   ^ RIHp V! 4       pM6\        P                  P                  4       pV e   W8w  d   ^ RIHp V! V4       \         F  pVP                  VR4       K  	  RV\        &   V# )uÜ  Return an environment that cannot self-identify as the gateway owner.

One updater environment relaunches EVERY profile, so a child for another profile would inherit
this process's authorization gates (``DISCORD_ALLOWED_CHANNELS``, ``GATEWAY_ALLOW_ALL_USERS`` ...)
and enforce them as its own â€” its ``.env`` only overwrites the keys it defines (#113270). Gates are
dropped when *profile* is not the launch profile; a same-profile child keeps an operator export.

Restarting the host multiplexer from a named profile does not copy this process's environ: the
child is ``host_gateway_child_env`` (``served_profile_child_env`` for the default root) so the
launching profile's platform credentials never become the primary adapter's.
Nr7   )Úhost_gateway_child_env)Ústrip_profile_gate_envÚ1)r@   Útools.environments.localrD   r8   r9   ÚcopyÚ#tools.environments.local_env_policyrE   Ú_GATEWAY_MARKERSÚpopÚ_RECOVERY_ENV)rB   ÚlaunchÚtargetrD   ÚenvrE   Úmarkers   &      r   Ú_child_environmentrQ   i   s   € ô Ó€FØÒ+‰W°€FØ�Ô˜v¨Ô2ÝCÙ$Ó&‰ä�j‰j�o‰oÓˆØÒ 7Ô#4ÝRÙ" 3Ô'ß"ˆØ�‰�˜Öñ #à€CŒÑØ€Jr   c               ó$   € V ^8„  d   QhRRRRRR/# ©r
   rB   r%   r   r   r   r.   r   )r   s   "r   r   r   …   s'   € ÷ Yñ Y #ð YÐ/Að YÀdñ Yr   c          	     ó.  € R\         P                  R\        V 4      /p\        P                  R8X  d,   \        \         R^ 4      \        \         R^ 4      ,          VR&   MRVR&   \        P                  R	R
RV RRRR.	p\        \        W3R\        /VB 4      # )zGRun one profile restart without inheriting the updater's process state.ÚstdinrO   ÚntÚCREATE_NEW_PROCESS_GROUPÚDETACHED_PROCESSÚcreationflagsTÚstart_new_sessionz-mzhermes_cli.mainz-pÚgatewayÚrestartz--interruptz--detachr   )r    ÚDEVNULLrQ   r8   Únamer)   ÚsysÚ
executabler1   r"   Ú_PROFILE_RESTART_TIMEOUT)rB   r   Úkwargsr   s   &$  r   Ú_run_profile_restartrc   …   s¢   € à%¤z×'9Ñ'9¸5ÔBTÐU\ÓB]Ð^€FÜ	‡w�w�$„Ü")¬*Ð6PÐRSÓ"TÔW^Ô_iÐk}ð  @Aó  XBõ  #BˆˆÒà&*ˆÐ"Ñ#ô �N‰N˜DÐ"3°T¸7ÀIÈyÐZgÐisÐt€DÜ”j ÑWÔ4LÐWÐPVÑWÓXÐXr   c               ó    € V ^8„  d   QhRRRR/# )r
   rB   r%   r   ztuple[str, ...]r   )r   s   "r   r   r   “   s   € ÷ Oñ O cð O¨oñ Or   c                ó,   € V R8X  d   R# RV  R2RV  R23# )zGUnit names the existing systemd gateway lifecycle produces per profile.r7   zhermes-gateway-ú.servicezgateway-)zhermes-gateway.servicezgateway.servicezgateway-default.servicer   )rB   s   &r   Ú_systemd_unit_candidatesrg   “   s-   € à�)ÔØWÐWØ˜g˜Y hÐ/°8¸G¸9ÀHÐ1MÐNÐNr   c               ó$   € V ^8„  d   QhRRRRRR/# rS   r   )r   s   "r   r   r   š   s"   € ÷ ñ  cð Ð3Eð È$ñ r   c               óô   aa€ \         P                  ! R4      o\        S4      ;'       dO    \        ;QJ d)    VV3R l\	        V 4       4       F  '       g   K   R# 	  R# ! VV3R l\	        V 4       4       4      # )u  True only when systemd itself reports the profile's unit active â€” the observation separating
``verified`` from ``relaunch_attempted``. Any failure (no ``systemctl``, probe error, unit not
``active``) means we could NOT verify, never that the restart failed.Ú	systemctlc              3  óF   <"  € T F  p\        SR .VSRR7      x € K  	  R# 5i)ú--userT)r   Úrequire_rc0N)Ú_unit_is_active)Ú.0Úunitr   rj   s   & €€r   Ú	<genexpr>Ú+_systemd_verified_active.<locals>.<genexpr>Ÿ   s+   øé € ð #á5ˆDô 	˜ HÐ-¨t¸È$×OÑOÛ5ùs   ƒ!TF)ÚshutilÚwhichr.   Úanyrg   )rB   r   rj   s   &d@r   Ú_systemd_verified_activerv   š   sh   ù€ ô —’˜[Ó)€IÜ�	‹?÷ ð Ÿs›sõ #ä,¨WÔ5ó#Ÿsœsð šsð ˜sõ #ä,¨WÔ5ó#ó  ð r   c               ó   € V ^8„  d   QhRR/# r3   r   )r   s   "r   r   r   ¥   s   € ÷ ?ñ ?˜ñ ?r   c                 ó®  € \         P                  P                  R4      p V '       d   V # \         P                  P                  R4      ;'       g    Rp\         P                  P	                  V4      '       g?   \         P                  P                  \         P                  P                  R4      RR4      p\         P                  P                  VRR4      # )	u  The path ``gateway.host_rendezvous.host_state_dir()`` resolves, computed locally.

This module imports no Hermes code at runtime â€” importing the freshly pulled tree is exactly
what aborted the phase that calls us â€” so the rule is duplicated here rather than shared.
ÚHERMES_GATEWAY_LOCK_DIRÚXDG_STATE_HOMEr(   Ú~z.localÚstateÚhermeszgateway-locks)r8   r9   r:   r;   ÚisabsÚjoinÚ
expanduser)ÚoverrideÚ
state_homes     r   Ú_host_state_dirrƒ   ¥   s‰   € ô �z‰z�~‰~Ð7Ó8€HßØˆÜ—‘—‘Ð 0Ó1×7Ð7°R€JÜ�7‰7�=‰=˜×$Ò$Ü—W‘W—\‘\¤"§'¡'×"4Ñ"4°SÓ"9¸8ÀWÓMˆ
Ü�7‰7�<‰<˜
 H¨oÓ>Ð>r   c               ó    € V ^8„  d   QhRRRR/# )r
   Úpidr   r   r.   r   )r   s   "r   r   r   ´   s   € ÷ ñ �cð ˜dñ r   c                ó  €  ^ RI p\        VP                  V 4      4      #   \         d     Mi ; i\        P
                  R8X  d   R#  \        P                  ! T ^ 4       R#   \         d     R# \         d     R# i ; i)u  Liveness of ``pid``: ``psutil`` when importable, else the POSIX signal-0 probe.

The signal probe is POSIX-only by construction â€” on Windows ``os.kill(pid, 0)`` sends a real
control event and can kill the target â€” so an unimportable psutil there means "cannot prove".
NrV   FT)	Úpsutilr.   Ú
pid_existsÚ	Exceptionr8   r^   ÚkillÚPermissionErrorr   )r…   r‡   s   & r   Ú_pid_is_liverŒ   ´   sv   € ðÛä�F×%Ñ% cÓ*Ó+Ð+øÜô Ùðúä	‡w�w�$„ÙðÜ
�Š��QŒñ
 øô	 ô ÚÜô Úðús*   ‚   .­.Á	A" Á"A>Á0A>Á9A>Á=A>c               ó   € V ^8„  d   QhRR/# )r
   r   zset[str]r   )r   s   "r   r   r   Ë   s   € ÷ Iñ I˜xñ Ir   c                 óè  €  \        \        P                  P                  \	        4       R4      RR7      ;_uu_ 4       p \
        P                  ! V 4      pRRR4       \        X\        4      '       d   TP                  R4      R8w  d   \        4       # TP                  R4      pTP                  R4      p\        T\        4      '       d/   T^ 8:  g(   \        T\        4      '       d   \!        T4      '       g   \        4       # T Uu0 uF'  p\        T\"        4      '       g   K  T'       g   K%  TkK)  	  up#   + '       g   i     Lê; i  \        \        \        3 d    \        4       u # i ; iu upi )	uœ  Profiles the ONE live host gateway multiplexes, from its rendezvous record.

Restarting any one of them restarts the same process, so they are a single restart target.
Empty (no collapsing, today's per-profile behaviour) when the record is absent, unreadable,
dead, or when liveness cannot be probed â€” a missed collapse costs an extra restart, a wrong
one would skip a profile that really has its own process.
zhost-gateway.jsonz	utf-8-sig)r   NÚroler[   r…   r6   )Úopenr8   r;   r   rƒ   ÚjsonÚloadr   ÚUnicodeDecodeErrorÚ
ValueErrorÚsetÚ
isinstanceÚdictr:   r   ÚlistrŒ   r%   )ÚhandleÚrecordr…   r6   r^   s        r   Ú_host_served_profilesr›   Ë   s  € ðÜ”"—'‘'—,‘,œÓ0Ð2EÓFÐQ\×]Õ]ÐagÜ—Y’Y˜vÓ&ˆF÷ ^ô �fœd×#Ò# v§z¡z°&Ó'9¸YÔ'FÜ‹uˆØ
�*‰*�UÓ
€CØ�z‰z˜*Ó%€HÜ�cœ3×Ò 3¨!¤8´:¸hÌ×3MÒ3MÔUaÐbe×UfÒUfÜ‹uˆÙ%ÓH™X�T¬°D¼#×)>ŒDÄ4�DˆD™XÑHÐH÷ ^×]ûäÔ'¬Ð4ô Ü‹uŠðüò Is@   ‚;E	 ½D6ÁE	 ÄE/Ä#E/Ä-E/Ä6E	ÅE	 ÅE	 Å	 E,Å+E,Úsupervisorsr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r
   r6   zIterable[str]rœ   zMapping[str, str] | Noner   r   r   zdict[str, Any]r   )r   s   "r   r   r   á   s,   € ÷ #ñ #Øð#Ø-Eð#ØSeð#àñ#r   c          	     ó�  € T;'       g    / pR. R. R. /p\        V  Uu0 uF'  p\        V\        4      '       g   K  V'       g   K%  VkK)  	  up4      p\        4       pV Uu. uF  qwV9   g   K  VNK  	  pp\	        V4      ^8”  d
   V^ ,          MRp	V	'       d
   VR,          M. p
V Fƒ  pWz9   d   K  \        WrR7      '       g   RpM-VP                  V4      R8X  d   \        WrR7      '       d   RpMRpW;,          P                  V4       Wy8X  g   Kl  W;,          P                  V
4       K…  	  V	'       d   Wš/M/ VR&   V# u upi u upi )	a‚  Restart the supplied profiles (only ones whose inventory identified a service supervisor).

Profiles served by the SAME host gateway process are one restart target: a host multiplexes
every profile, so N payload profiles meant N sequential ``gateway restart`` calls, each
killing the successor the previous pass had just verified. The group is restarted exactly
once through one representative and the rest are reported under ``covered`` with that
restart's outcome.

A profile only lands in ``verified`` when its supervisor is systemd and ``systemctl --user is-
active`` independently confirms the unit after the relaunch command succeeded.
ÚverifiedÚrelaunch_attemptedÚfailedN:é   NN©r   ÚsystemdÚcovered)
Úsortedr–   r%   r›   Úlenrc   r:   rv   ÚappendÚextend)r6   rœ   r   r$   ÚpÚ	requestedÚservedrB   ÚgroupÚrepresentativer¥   Úbuckets   &$$         r   Úrestart_profilesr°   á   s$  € ð ×#Ð# €KØ(¨"Ð.BÀBÈÐRTÐU€FÜ¡8ÓH¡8˜a¬z¸!¼S×/AœÄaŸ˜¡8ÑHÓI€IÜ"Ó$€FÙ$-ÓC¡I˜¸FÑ1B�WˆW¡I€EÐCÜ!$ U£¨a¤�U˜1–X°T€Nß)ˆe�BŽi¨r€GÛˆØÔÙÜ# G×5Ó5Ø‰FØ�_‰_˜WÓ%¨Ô2Ô7OÐPW×7aÓ7aØ‰Fà)ˆFØ�×Ñ˜gÔ&ØÖ$à�N×!Ñ! 'Ö*ñ ÷ 6D˜Ñ1È€Fˆ9ÑØ€Mùò' IùâCs   žD>»D>ÁD>Á EÁ-Ec               ó   € V ^8„  d   QhRR/# )r
   r   zlist[tuple[str, list[str]]]r   )r   s   "r   r   r     s   € ÷ 
Fñ 
FÐ6ñ 
Fr   c                 ó‚   € \         P                  ! R4      p V '       d   \        P                  R8w  d   . # RV R.3RV .3.# )uˆ  ``(label, systemctl argv)`` for the user and system scopes (the pair the in-process phase walks), or nothing.

``systemctl`` comes from ``shutil.which`` so this module never imports a Hermes platform helper â€”
importing the freshly pulled tree is exactly what aborted the phase that called us. Scopes carry
their label because the same unit name in both managers is two different processes.
rj   ÚlinuxÚuserrl   Úsystem)rs   rt   r_   Úplatform)rj   s    r   Ú_systemctl_scopesr·     sA   € ô —’˜[Ó)€IßœŸ™¨Ô/Øˆ	Ø�i Ð*Ð+¨h¸¸Ð-DÐEÐEr   c               ó$   € V ^8„  d   QhRRRRRR/# )r
   Úscoper   r   r   r   r   )r   s   "r   r   r     s"   € ÷ ñ ˜yð Ð2Dð Èñ r   c          
     ó�  € . p\          F¹  p\        VV RVRRR.,           \        R7      pVf   K'  \        VRR4      ;'       g    RP	                  4        Fi  pVP                  4       pV'       g   K  \        P                  V^ ,          4      '       g   KA  V^ ,          V9  g   KQ  VP                  V^ ,          4       Kk  	  K»  	  V# )zJServe/dashboard units systemd knows about in one scope, validated by name.z
list-unitsz--plainz--no-legendz
--no-pager©r   r'   r(   )	Ú_SERVE_UNIT_PATTERNSr"   Ú_VERIFY_TIMEOUTr)   Ú
splitlinesÚsplitÚ_UNIT_REÚ	fullmatchr¨   )r¹   r   ÚunitsÚpatternr$   ÚlineÚpartss   &$     r   Ú_listed_serve_unitsrÆ     s«   € à€Eß'ˆÜØØ�\ 7¨I°}ÀlÐSÕSÜ#ô
ˆð
 Š>Ùô ˜V X¨rÓ2×8Ð8°b×DÑDÖFˆDØ—J‘J“LˆEß‰uœ×+Ñ+¨E°!­H×5Ô5¸%À½(È%Ö:OØ—‘˜U 1�XÖ&ó Gñ (ð €Lr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r
   r¹   r   rp   r%   r   r   r   r   r   )r   s   "r   r   r   (  s)   € ÷ ñ ˜)ð ¨3ð Ð8Jð Èsñ r   c               óÂ   € \        W RVRR.,           \        R7      p \        V4      '       d   \        \	        V4      ;'       g    ^ 4      # ^ #   \
         d     ^ # i ; i)zOThe unit's ``MainPID`` via ``systemctl show``; ``0`` when absent or unreadable.Úshowz--property=MainPIDz--valuer»   )r"   r½   r1   r   r,   r”   )r¹   rp   r   r$   s   &&$ r   Ú_unit_main_pidrÊ   (  s[   € ä˜ f¨dÐ4HÈ)Ð%TÕTÔ^mÔn€FðÜ,6°v×,>Ò,>Œs”7˜6“?×'Ð' aÓ(ÐEÀAÐEøÜô Úðús   ž'A ÁA ÁA ÁAÁArm   Fc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R/# )
r
   r¹   r   rp   r%   r   r   rm   r.   r   r   )r   s   "r   r   r   1  s2   € ÷ 'ñ '˜9ð '¨Cð 'Ð9Kð 'ÐZ^ð 'Ðkoñ 'r   c               ó�   € \        W R V.,           \        R7      pVe   V'       d   \        V4      '       g   R# \        V4      R8H  # )z	is-activer»   FÚactive)r"   r½   r1   r,   )r¹   rp   r   rm   r$   s   &&$$ r   rn   rn   1  s;   € Ü˜ k°4Ð%8Õ8Ä/ÔR€FØ‚~Ÿ+¬j¸×.@Ò.@ÙÜ�6‹?˜hÑ&Ð&r   c               ó0   € V ^8„  d   QhRRRRRRRRR	R
RR/# )r
   r¹   r   rp   r%   Úprevious_pidr   r   r   ÚsleepúCallable[[float], Any]r   r.   r   )r   s   "r   r   r   8  s<   € ÷ ñ ØðØðØ/2ðØ<NðØWmðà	ñr   c               óÂ   € \        \        4       FK  pV'       d   V! \        4       \        WVR7      '       g   K,  \	        WVR7      pV^ 8”  g   KB  Wb8w  g   KJ   R# 	  R# )a>  Did the unit come back on a NEW main process?

``restart`` returning 0 is not evidence: a live process can keep serving the pre-update
generation while every status command reports success. A changed ``MainPID`` on an ``active``
unit is the observation that the old interpreter and its stale ``sys.modules`` are gone.
r£   TF)ÚrangeÚ_UNIT_SETTLE_ATTEMPTSÚ_UNIT_SETTLE_DELAYrn   rÊ   )r¹   rp   rÏ   r   rÐ   ÚattemptÚcurrents   &&&$$  r   Ú_serve_unit_replacedrØ   8  sM   € ô Ô.Ö/ˆßÙÔ$Ô%Ü˜5¨C×0Õ0Ü$ U°cÔ:ˆGØ˜Ž{˜wÖ6Úñ 0ñ r   c               ó    € V ^8„  d   QhRRRR/# )r
   Úentryr   r   ztuple[str, str]r   )r   s   "r   r   r   K  s   € ÷ 	6ñ 	6˜Sð 	6 _ñ 	6r   c                ó4  € \        V \        4      '       dJ   \        V P                  R4      ;'       g    R4      p\        V P                  R4      ;'       g    R4      pM(\        V 4      P	                  R4      w  rpV'       g   RTr!WP                  R4      3# )z[``(scope_label, base_unit)`` of a skip entry in either the mapping or ``scope/unit`` shape.r¹   r(   rp   Ú/rf   )r–   r   r%   r:   Ú	partitionÚremovesuffix)rÚ   Úscope_labelrp   Úseps   &   r   Ú_split_skip_entryrá   K  s|   € ä�%œ×!Ò!Ü˜%Ÿ)™) GÓ,×2Ð2°Ó3ˆÜ�5—9‘9˜VÓ$×*Ð*¨Ó+‰ä!$ U£×!5Ñ!5°cÓ!:Ñˆ˜$ßØ " K˜Ø×)Ñ)¨*Ó5Ð5Ð5r   c               ó    € V ^8„  d   QhRRRR/# )r
   Ú
skip_unitsúIterable[Any]r   z%tuple[set[tuple[str, str]], set[str]]r   )r   s   "r   r   r   W  s   € ÷ 	ñ 	 -ð 	Ð4Yñ 	r   c                óà   € \        4       p\        4       pT ;'       g    R FH  p\        V4      w  rEV'       g   K  V\        9   d   VP                  WE34      MVP                  V4       KJ  	  W3# )z®Split already-settled units into scope-qualified and legacy entries (a bare ``"hermes-serve"``
carries no scope and cannot say WHICH of two same-named processes was settled).r   )r•   rá   Ú_SCOPE_LABELSÚadd)rã   Ú	qualifiedÚlegacyrÚ   rß   Úbases   &     r   Ú_normalized_skipsrë   W  sj   € ô '*£e€IÜ“u€FØ×!Ð!˜rÒ!ˆÜ-¨eÓ4Ñˆß‰4Ø3>Ä-Ô3OˆY�]‰]˜KÐ.Ô/ÐU[×U_ÑU_Ð`dÓUeúñ "ð ÐÐr   rã   rÐ   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r
   rã   rä   r   r   rÐ   rÑ   r   zdict[str, list[str]]r   )r   s   "r   r   r   c  s,   € ÷ "ñ "Ø ð"Ø,>ð"ØXnð"àñ"r   c                óL  € \        V 4      w  r4/ p\        4       p\        4        F¼  w  rx\        W�R7       F§  p	V	P	                  R4      p
Wz3pW¶9   g   W³9   g   W¤9   d   K+  VP                  V4       \        W‰VR7      '       g   KQ  \        W‰VR7      pV^ 8„  ;'       d;    \        \        WRRV	.,           \        R7      4      ;'       d    \        W‰WÁVR7      W[&   K©  	  K¾  	  R\        R VP                  4        4       4      R	\        R
 VP                  4        4       4      /# )a
  Restart every active ``hermes-serve*``/``hermes-dashboard*`` systemd unit from this process.

Units are enumerated from systemd, never from the update inventory, so a manually launched or
Desktop-owned ``hermes serve`` (no unit) structurally cannot be touched here.
r£   rf   z--no-ask-passwordr\   r»   )r   rÐ   rŸ   c              3  óL   "  € T F  w  w  rq3'       g   K  V R V 2x € K  	  R# 5i©rÜ   Nr   ©ro   r¹   rê   Úoks   &   r   rq   Ú&restart_serve_units.<locals>.<genexpr>ƒ  s*   é € Ð]ÑFVÑ1B±°%ÀÓZ\Ô,˜e˜W A d VÕ,ÓFVùó   ‚$•$r¡   c              3  óL   "  € T F  w  w  rq3'       d   K  V R V 2x € K  	  R# 5irï   r   rð   s   &   r   rq   rò   „  s*   é € Ð_ÑDTÑ/@©}°¸bÓ\^Ô*˜E˜7 ! D 6Õ*ÓDTùró   )rë   r•   r·   rÆ   rÞ   rç   rn   rÊ   r1   r"   Ú_UNIT_RESTART_TIMEOUTrØ   r¦   Úitems)rã   r   rÐ   Úskipped_qualifiedÚskipped_legacyÚoutcomesÚseenrß   r¹   rp   rê   rN   rÏ   s   $$$          r   Úrestart_serve_unitsrû   c  s!  € ô ):¸*Ó(EÑ%Ðð -/€HÜ!$£€DÜ/Ö1ÑˆÜ'¨×7ˆDØ×$Ñ$ ZÓ0ˆDØ!Ð(ˆFØŒ~ Ô!<ÀÔ@VÙØ�H‰H�VÔÜ" 5°C×8Ó8ÙÜ)¨%¸3Ô?ˆLð
  ,¨aÑ/÷  Xð  X´JÜ˜3Ð)<¸iÈÐ(NÕ NÔXmÔnó5÷  Xð  Xä& u°LÐQVÔWð Óó 8ñ 2ð& 	”FÑ]ÀhÇnÁnÔFVÓ]Ó]Ø”&Ñ_ÀHÇNÁNÔDTÓ_Ó_ðð r   c               ó   € V ^8„  d   QhRR/# )r
   r   z1tuple[list[str], dict[str, str], bool, list[str]]r   )r   s   "r   r   r   ˆ  s   € ÷ 0<ñ 0<ÐOñ 0<r   c                óÚ  € \         P                  ! V 4      p\        V\        4      '       g   / pVP	                  R 4      p\        V\
        4      '       g   \        R4      h\        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        R4      hVP	                  R4      p/ pVeƒ   \        V\        4      '       dW   \        ;QJ d*    R VP                  4        4       F  '       g   K   RM	  RM! R VP                  4        4       4      '       d   \        R4      h\        V4      pVP	                  R	4      pRp. pVEe‘   \        V\        4      '       g   \        R
4      h\        VP	                  R4      4      pVP	                  R4      ;'       g    . p\        V\
        4      '       d;   \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        R4      hV FÙ  p	\        V	\        4      '       da   \        V	P	                  R4      \        4      '       g   \        R4      h\        V	P	                  R4      \        4      '       g   RV	R,          /p	\        V	4      w  r«V
'       d   V
\        9  g   \        P                  V R24      '       g   K¹  TP                  V
'       d   V
 RV 2MT4       KÛ  	  W$Wg3# )r6   z-recovery payload must contain a profiles listc              3  ó’   "  € T F=  p\        V\        4      '       * ;'       g    \        P                  ! V4      '       * x € K?  	  R # 5i©N)r–   r%   Ú_PROFILE_ID_RErÁ   )ro   rB   s   & r   rq   Ú!_parse_payload.<locals>.<genexpr>�  s6   é € Ð
iÑ`hÐU\Œz˜'¤3Ó'Ô'×PÐP¬~×/GÒ/GÈÓ/PÔ+PÔPÓ`hùs
   ‚ A£$ATFz/recovery profiles contain an invalid profile idrœ   c              3  ó  "  € T F~  w  r\        V\        4      '       * ;'       g[    \        V\        4      '       * ;'       g>    \        P                  ! V4      '       * ;'       g    \        P                  V4      '       * x € K€  	  R # 5irÿ   )r–   r%   r   rÁ   Ú_SUPERVISOR_RE)ro   rB   Ú
supervisors   &  r   rq   r  ”  s|   é € ð 8
ñ
 (?Ñ#�ô	 ˜7¤CÓ(Ô(÷ 8ð 8Ü˜j¬#Ó.Ô.÷8ð 8ä!×+Ò+¨GÓ4Ô4÷8ð 8ô "×+Ñ+¨JÓ7Ô7ô8ó (?ùs   ‚"B¥BÁ"BÁ%#Bz#recovery supervisors map is invalidÚserve_unitsz%recovery serve_units block is invalidÚrecoverÚskipc              3  óX   "  € T F   p\        V\        \        34      '       * x € K"  	  R # 5irÿ   )r–   r%   r—   )ro   rÚ   s   & r   rq   r  ¥  s$   é € Ð0jÑaiÐX]´ZÀÌÌTÀ{Ó5S×1SÑ1SÓaiùs   ‚(*z)recovery serve_units skip list is invalidrp   r¹   rf   rÜ   )r‘   r’   r–   r—   r:   r˜   r”   ru   rö   r.   r%   rá   ræ   rÀ   rÁ   r¨   )ÚstreamÚpayloadr6   Úraw_supervisorsrœ   Ú	raw_serveÚrecover_serverã   Úraw_skiprÚ   rß   rê   s   &           r   Ú_parse_payloadr  ˆ  sT  € Ü�iŠi˜Ó€GÜ�gœt×$Ò$ØˆØ�{‰{˜:Ó&€HÜ�h¤×%Ò%ÜÐHÓIÐIß
ƒsÑ
iÑ`hÓ
i‡s‡s‚sÑ
iÑ`hÓ
i×iÒiÜÐJÓKÐKØ—k‘k -Ó0€OØ"$€KØÒ"Ü˜/¬4×0Ò0·C³Cñ 8
ð
 (7×'<Ñ'<Ô'>ó8
·C·C²Cñ 8
ð
 (7×'<Ñ'<Ô'>ó8
÷ 5
ò 5
ô ÐBÓCÐCÜ˜?Ó+ˆØ—‘˜MÓ*€IØ€MØ€JØÓÜ˜)¤T×*Ò*ÜÐDÓEÐEÜ˜YŸ]™]¨9Ó5Ó6ˆØ—=‘= Ó(×.Ð.¨BˆÜ˜(¤D×)Ò)¯S«SÑ0jÑaiÓ0j¯S¯SªSÑ0jÑaiÓ0j×-jÒ-jÜÐHÓIÐIÛˆEô
 ˜%¤×&Ò&Ü! %§)¡)¨FÓ"3´S×9Ò9Ü$Ð%PÓQÐQÜ! %§)¡)¨GÓ"4´c×:Ò:Ø# U¨6¥]Ð3�EÜ 1°%Ó 8ÑˆK÷  ´=Ô @Ì×I[ÑI[Ð_cÐ^dÐdlÐ\m×InÒInÙØ×Ñ¿  ¨Q¨t¨fÑ5È$ÖOñ! ð"  -Ð;Ð;r   c               ó    € V ^8„  d   QhRRRR/# )r
   r   zlist[str] | Noner   r   r   )r   s   "r   r   r   »  s   € ÷ Kñ KÐð K¨3ñ Kr   c                óÂ  € \         P                  ! \        R 7      pVP                  RR\         P                  R7       VP                  V 4      pVP                  '       g   VP                  R4        \        \        P                  4      w  r4rV\        W4R7      pV'       d   \        VR7      MR. R. /VR	&   \        \        P                   ! TRR7      4       TR,          '       g   TR	,          R,          '       d   ^# ^ #   \        \        P                  3 dB   p\        \        P                   ! R
\#        T4      R. R. R. R	R. R. //4      4        Rp?^# Rp?ii ; i))Údescriptionz--stdinÚ
store_true)ÚactionÚhelpz7this command is an internal update-recovery entry point)rœ   )rã   rŸ   r¡   r  Úerrorr    NT)Ú	sort_keys)ÚargparseÚArgumentParserÚ__doc__Úadd_argumentÚSUPPRESSÚ
parse_argsrU   r  r  r_   r°   rû   r”   r‘   ÚJSONDecodeErrorÚprintÚdumpsr%   )	r   ÚparserÚargsr6   rœ   r  rã   r$   Úexcs	   &        r   Úmainr$  »  s0  € Ü×$Ò$´Ô9€FØ
×Ñ˜	¨,¼X×=NÑ=NÐÔOØ×Ñ˜TÓ"€DØ�:�:ˆ:Ø�‰ÐNÔOðÜ;IÌ#Ï)É)Ó;TÑ8ˆ˜}Ü! (ÔDˆç:GÔ¨:Õ6ÈjÐZ\Ð^fÐhjÐMkð 	ˆ}Ñô 
Œ$�*Š*�V tÔ
,Ô-Ø�x× Ô  F¨=Õ$9¸(×$CÔ$Cˆ1ÐJÈÐJøô œ×,Ñ,Ð-ô ÜŒd�jŠjØ”S˜“X˜z¨2Ð/CÀRÈÐSUØ˜J¨¨H°bÐ9ð
ó ô 	õ ûðús   Á3AD ÄEÄ6EÅEÚ__main__)Ú_HERMES_GATEWAYÚHERMES_GATEWAYÚHERMES_GATEWAY_MODE)zhermes-serve*zhermes-dashboard*)r´   rµ   rÿ   r   ):r  Ú
__future__r   r  r‘   r8   Úrers   r    r_   ÚtimeÚcollections.abcr   r   r   Útypingr   rL   rJ   ra   r½   Úhermes_constantsr   r   Úcompiler  rÀ   r¼   ræ   rõ   rÔ   rÕ   r"   r,   r1   r@   rQ   rc   rg   rv   rƒ   rŒ   r›   r   r°   r·   rÆ   rÊ   rn   rØ   rá   rë   rÐ   rû   r  r$  Ú__name__Ú
SystemExitr   r   r   Ú<module>r2     sX  ðñ+õZ #ã Û Û 	Û 	Û Û Û 
Û ß 7Ñ 7Ý à0€ØOÐ ØÐ Ø€Ý <à—’Ð9Ó:€Ø�:Š:ÐXÓY€Ø=Ð Ø"€ØÐ ØÐ ØÐ õõ9õHõ	÷õ8YõOõõ?õõ.Ið,#ØHLð#Øhr×hvÑhv÷#õL
Fõõ(ð'Ðaf÷ 'õõ&	6õ	ð"Ø#%ð"ØAKÇÁð"Øqu×q{Ñq{÷"õJ0<÷fKð0 ˆzÔÙ
‘T“VÓ
Ðñ r   