+
    jHàj/k ã                   óˆ  a € R› ti0 t R t^ RIt^ RIHtHtHtH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IHt ]P,                  ! R4      tRœtRR/R R	 llt]R
 R l4       tR R ltR R ltR R ltR R ltR R ltR R lt R R lt!R t"R R lt#RR/R R llt$R  R! lt%]&! 0 R�m4      t'Rs(] ^ k R" R# lt)R$ R% lt*R& R' lt+R( R) lt,^t-R* R+ lt.R, R- lt/R. R/ lt0R0 R1 lt1R2 R3 lt2R4 R5 lt3R6 R7 lt4R8 R9 lt5R: R; lt6R< R= lt7R> R? lt8R@ RA lt9RB RC lt:RD RE lt;RF RG lt<RH RI lt=RJ RK lt>RžRL RM llt?RN RO lt@RP RQ ltARRRŸRSRRTRRURV/RW RX lltBRURV/RY RZ lltCRUR[/R\ R] lltDR^ R_ ltE ! R` Ra]F4      tGRb Rc ltHRdRŸReRf/Rg Rh lltIRi tJR Rj ltKRk Rl ltLRm Rn ltMRo Rp ltNR¡Rq Rr lltORs Rt ltPRu Rv ltQR Rw Rx lltRRy Rz ltSR¢R{ R| lltTR[tUR}tVR[tWR~tXR R R€ lltYR� R‚ ltZRƒ R„ lt[R… R† lt\RVt]R‡ Rˆ lt^R‰ RŠ lt_R‹ RŒ lt`R�taRŽtbR R� R� lltcR‘ R’ ltdR“ R” lteR• R– ltfR— R˜ ltgR™ Rš lthR# )£ah  Windows gateway lifecycle for ``hermes update``: pause/resume/cold-start the service, sweep venv holders, reap orphaned backends.

Split out of ``update_cmd.py``; names are re-imported there so ``hermes_cli.update_cmd.<name>`` still resolves/monkeypatches.
Origin helpers are imported lazily per function (no cycle; test patches on the origin stay effective).
N)ÚcontextmanagerÚnullcontextÚredirect_stdoutÚsuppress)ÚdatetimeÚtimezoneÚUTC©ÚPath)Ú_best_effortzhermes_cli.update_cmdÚdefaultc                ó$   € V ^8„  d   QhR\         /# )é   Úlog_message©Ústr)Úformats   "ÚB/home/ubuntu/.hermes/hermes-agent/hermes_cli/update_cmd_windows.pyÚ__annotate__r      s   € ÷ ñ œsñ ó    c               óz   €  V ! 4       #   \          d'   p\        P                  ! T.TOTN5!   Tu Rp?# Rp?ii ; i)zf``fn()``, or *default* after logging the exception at debug (``log_message`` gets ``*log_args, exc``).N)Ú	ExceptionÚloggerÚdebug)Úfnr   r   Úlog_argsÚexcs   &&$* r   Ú	_try_callr      s9   € ðÙ‹tˆøÜô Ü�Š�[Ð1 8Ð1¨SÔ1Ø�ûðús   ‚	 ‰:”5¯:µ:c                ó$   € V ^8„  d   QhR\         /# )r   Úprefixr   )r   s   "r   r   r   #   s   € ÷ 8ñ 8œCñ 8r   c              #  ó`   "  €  Rx € R#   \          d   p\        T  RT 24      ThRp?ii ; i5i)z[Re-raise any failure of a mandatory step as ``RuntimeError(f"{prefix}: {exc}")`` (chained).Nú: )r   ÚRuntimeError)r   r   s   & r   Ú_abort_on_errorr#   "   s4   é € ð8ÝøÜô 8Ü˜f˜X R¨ uÐ-Ó.°CÐ7ûð8üs   ‚.„
 ˆ.Š+•&¦+«.c                ó0   € V ^8„  d   QhR\         R\         /# )r   Úprofile_pathÚreturnr	   )r   s   "r   r   r   +   s   € ÷ =ñ =¬Dð =´Tñ =r   c                 ó&   € \        V 4      R ,          # )z.gateway-planned-stop.jsonr	   )r%   s   &r   Ú_planned_stop_marker_pathr(   +   s   € Ü�ÓÐ <Õ<Ð<r   c                ó$   € V ^8„  d   QhR\         /# ©r   r&   ©Údict)r   s   "r   r   r   /   s   € ÷ ñ ÔTXñ r   c                ó¤   € / pV  FG  pWB9   d   RM\        VP                  V4      RR4      pV'       g   K1  \        \        V4      4      W4&   KI  	  V# )z\``{pid: marker path}`` for each gateway the socket pause will ask (profile-mapped, not SCM).NÚpath)ÚgetattrÚgetr(   r
   )Úrunning_pidsÚprofile_processesÚservice_gateway_pidsÚmarkersÚpidÚhomes   &&&   r   Ú_planned_stop_markersr7   /   sQ   € à€GÛˆØÔ2‰t¼Ð@Q×@UÑ@UÐVYÓ@ZÐ\bÐdhÓ8iˆß‰4Ü4´T¸$³ZÓ@ˆG‹Lñ ð €Nr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   r%   r5   r&   )r
   ÚintÚbool)r   s   "r   r   r   9   s!   € ÷ ñ ´Dð ¼sð Ätñ r   c                ó  €  ^ RI Hp ^ RIHp V! \	        V 4      RVRV! V4      R\
        P                  ! 4       R\        P                  ! \        4      P                  4       /RRR7       R	#   \        \        3 d     R
# i ; i)z9Write a planned-stop marker into a specific profile home.)Ú_get_process_start_time)Úatomic_json_writeÚ
target_pidÚtarget_start_timeÚstopper_pidÚ
written_atN)ÚindentÚ
separatorsTF)Ú,Ú:)Úgateway.statusr<   Úutilsr=   r(   ÚosÚgetpidr   Únowr   Ú	isoformatÚOSErrorÚPermissionError)r%   r5   r<   r=   s   &&  r   Ú!_write_update_planned_stop_markerrN   9   sy   € ðÝ:Ý+ÙÜ% lÓ3Ø˜3Ð 3Ñ5LÈSÓ5QÐS`Ôbd×bkÒbkÓbmØœ8Ÿ<š<¬Ó,×6Ñ6Ó8ð:à Jõ		
ñ øÜ”_Ð%ô Úðús   ‚A(A, Á,BÂ Bc                óh   € V ^8„  d   QhR\         \        ,          R\        R\        \        ,          /# )r   ÚpidsÚtimeoutr&   )Úlistr9   ÚfloatÚset)r   s   "r   r   r   I   s,   € ÷ 5ñ 5´´Sµ	ð 5Äuð 5ÔQTÔUXÕQYñ 5r   c               óð   aaa€ V '       g   \        4       # ^ RIHo R V3R llo\        V 4      oR VV3R llp\        V\	        VR4      R4       S Uu0 uF  pS! V4      '       g   K  VkK  	  up# u upi )z=Wait for the given gateway PIDs to exit, returning survivors.©Ú_pid_existsc                ó0   € V ^8„  d   QhR\         R\        /# ©r   r5   r&   ©r9   r:   )r   s   "r   r   Ú;_wait_for_windows_update_gateway_exit.<locals>.__annotate__O   s   € ÷ ñ ”Cð œDñ r   c                 óL   <€  \        S! V 4      4      #   \         d     R # i ; i)F)r:   r   )r5   rW   s   &€r   Ú_aliveÚ5_wait_for_windows_update_gateway_exit.<locals>._aliveO   s*   ø€ ð	Ü™ CÓ(Ó)Ð)øÜô 	Úð	ús   ƒ ”#¢#c                ó$   € V ^8„  d   QhR\         /# r*   ©r:   )r   s   "r   r   r[   W   s   € ÷ ñ ”tñ r   c                  ó`   <€ S U u0 uF  p S! V 4      '       g   K  V kK  	  up oS'       * # u up i ©N© )r5   r]   Ú	remainings    €€r   Ú	_all_goneÚ8_wait_for_windows_update_gateway_exit.<locals>._all_goneW   s,   ø€ á$-Ó=¡I˜S±¸·—S�S¡IÑ=ˆ	ØŒ}Ðùò >s   †+›+ç        g      Ð?)rT   rF   rW   Ú_poll_untilÚmax)rP   rQ   re   r5   r]   rW   rd   s   &$  @@@r   Ú%_wait_for_windows_update_gateway_exitrj   I   sd   ú€ çÜ‹uˆÝ*÷ð ô �D“	€I÷ñ ô
 �	œ3˜w¨Ó,¨dÔ3Ù$Ó4™9�C©¨s¯�CˆC™9Ñ4Ð4ùÒ4s   ÁA3Á*A3c                ó:   € V ^8„  d   QhR\         \        ,          /# r*   )rT   r9   )r   s   "r   r   r   `   s   € ÷ ñ ´3´sµ8ñ r   c                óð  € Rp\        \        4      ;_uu_ 4        ^ RIHp RRR4       \        P
                  ! 4       0p\        \        4      ;_uu_ 4        V P                  4       P                  4        FN  p\        V4      pVe   V'       d   V! V4      '       d   K*  VP                  \        VP                  4      4       KP  	  RRR4       V#   + '       g   i     L¸; i  + '       g   i     T# ; i)a�  PIDs a venv-holder scan must never nominate: this process and its non-gateway ancestry.

Do NOT blanket-exclude ancestors: under ``/update`` the updater is a CHILD of the gateway, and hiding it
dead-ends the update on ``venv-blocked``. Gateway ancestors stay visible (the pause path stops them
gracefully; a detached child survives on Windows); interactive ancestry is never a blocker.N)Úlooks_like_gateway_command_line)r   r   rF   rm   rH   rI   ÚProcessÚparentsÚ_cmdline_or_emptyÚaddr9   r5   )ÚpsutilÚ_is_gwÚskipÚancÚanc_cmdlines   &    r   Ú#_self_and_non_gateway_ancestor_pidsrw   `   s¨   € ð €FÜ	”)×	Õ	õ
 	M÷ 
ô —i’i“k�]€DÜ	”)×	Õ	Ø—>‘>Ó#×+Ñ+Ö-ˆCÜ+¨CÓ0ˆKØÒ&¯;¹6À+×;NÔ;NØ—‘œ˜SŸW™W›Ö&ñ .÷ 
ð
 €K÷ 
×	ú÷ 
Ö	ð
 €Kús#   šCÁ8C$ÂC$Â(C$ÃC!	Ã$C5	c                ó$   € V ^8„  d   QhR\         /# r*   r   )r   s   "r   r   r   v   s   € ÷ ñ œsñ r   c                óz   €  RP                  V P                  4       ;'       g    . 4      #   \         d     R# i ; i)z>Joined argv of a psutil process, ``""`` when it can't be read.Ú Ú )ÚjoinÚcmdliner   ©Úprocs   &r   rp   rp   v   s6   € ðØ�x‰x˜Ÿ™›×,Ð,¨"Ó-Ð-øÜô Úðús   ‚!+ ¤+ «:¹:c                ó0   € V ^8„  d   QhR\         R\        /# )r   r.   r&   )r
   r   )r   s   "r   r   r   ~   s   € ÷ /ñ /œDð /¤Sñ /r   c                óò   €  \        V P                  4       4      pVP                  4       P	                  \
        P                  4      \
        P                  ,           #   \         d    \        T 4      p LZi ; i)z```str(path)`` lower-cased with one trailing separator, resolved when possible (prefix matching).)r   ÚresolverL   ÚlowerÚrstriprH   Úsep)r.   Úraws   & r   Ú_lower_dir_prefixr‡   ~   sW   € ðÜ�$—,‘,“.Ó!ˆð �9‰9‹;×ÑœbŸf™fÓ%¬¯©Õ.Ð.øô ô Ü�$‹iŠðús   ‚A ÁA6Á5A6c                 ó4   €  ^ RI p V #   \         d     R# i ; i)z\The ``psutil`` module, or ``None`` when it can't be imported (callers degrade, never raise).N)rr   r   )rr   s    r   Ú_psutilr‰   ‡   s%   € ðÛð €Møô ô Úðús   ‚ ˆ–c                ó$   € V ^8„  d   QhR\         /# r*   r`   )r   s   "r   r   r   �   s   € ÷ eñ eœTñ er   c                ó¬   € V P                  4       pVRJ;'       d:    VP                  4       ;'       d"    VP                  4       V P                  4       8*  # )zfTrue when *proc* has a running parent that is not a recycled PID (a "parent" created after its child).N)ÚparentÚ
is_runningÚcreate_time)r   rŒ   s   & r   Ú_parent_is_liver�   �   sI   € à�[‰[‹]€FØ˜Ð×dÐd &×"3Ñ"3Ó"5×dÐd¸&×:LÑ:LÓ:NÐRV×RbÑRbÓRdÑ:dÐdr   Úexclude_pidsc                ó–   € V ^8„  d   QhR\         \        ,          R,          R\        \        \        \        \        3,          ,          /# )r   r�   Nr&   )rT   r9   rR   Útupler   )r   s   "r   r   r   –   s7   € ÷ 1ñ 1´3´sµ8¸dµ?ð 1ÌdÔSXÔY\Ô^aÔcfÐYfÕSgÕNhñ 1r   c                óh  € ^ RI Hp \        4       pV! 4       P                  4       '       d   Vf   . # ^ RIHp V! V! 4       P                  4      ;'       g    V! 4       P                  R,          p\        V4      p\        V! 4       P                  4      p\        T ;'       g    \        4       4      \        V4      ,          p. p VP                  . RO4      p	T	 EF}  p
 T
P                  pTP                  R4      TP                  R4      rÜT'       d   Te   \        T4      T9   d   KP   \        \!        T4      P#                  4       4      P%                  4       pTP+                  T4      p\        TP                  R4      ;'       g    \!        T4      P,                  4      pTP%                  4       pT'       g"   TP+                  R	4      '       g   TR
9   g   EK  \/        T
4      pTP%                  4       pT'       g<   TT9   g5   RT9   g   EK6  TT9   g$   \1        T
4      P+                  T4      '       g   EK`  TP3                  \        T4      TT34       EK€  	  T#   \         d    . u # i ; i  \         d     EK¦  i ; i  \&        \(        3 d    \        T4      P%                  4       p ELVi ; i)ao  Live processes running from the project venv's interpreter as ``(pid, name, cmdline)``; never raises.

The hermes.exe shim guard misses the Desktop backend and anything off ``venv\Scripts\python(w).exe``;
they keep ``.pyd`` files mapped so a mid-update dependency sync dies half-way. Empty off-Windows / without
psutil; self + non-gateway ancestors excluded. cmdline/cwd are expensive per process on Windows (500+
procs can blow the Desktop preflight watchdog), so they are fetched lazily for plausible candidates only.
The FULL cmdline is kept: callers parse it (the pausable-gateway exemption looks for ``gateway run``).
©Ú_m©Úproject_venv_dirÚvenvr5   ÚexeÚnameúhermes_cli.main)r5   r™   rš   )ÚpythonÚpypy>   úuv.exeúuvx.exeú
hermes.exe)Úhermes_cli.update_cmdr•   r‰   Ú_is_windowsÚhermes_constantsr—   ÚPROJECT_ROOTr‡   rT   rw   Úprocess_iterr   Úinfor0   r9   r   r
   r‚   rƒ   rL   Ú
ValueErrorÚ
startswithrš   rp   Ú_cwd_prefixÚappend)r�   r•   rr   r—   Úvenv_dirÚvenv_prefixÚroot_prefixrt   ÚmatchesÚ	proc_iterr   r¦   r5   r™   Úexe_normÚin_venvrš   Úname_lowÚcmdline_rawÚcmdline_lows   $                   r   Ú_detect_venv_python_processesrµ   –   s+  € õ )Ü‹Y€FÙ‹4×Ñ×Ò ¢Øˆ	Ý1Ù¡£× 1Ñ 1Ó2×PÐP±b³d×6GÑ6GÈ&Õ6P€HÜ# HÓ-€KÜ#¡B£D×$5Ñ$5Ó6€KÜˆ|×$Ð$œs›uÓ%Ô(KÈFÓ(SÕS€DØ*,€GðØ×'Ñ'Ò(>Ó?ˆ	ô ˆð	Ø—9‘9ˆDð —8‘8˜E“? D§H¡H¨U£OˆSß�c’k¤S¨£X°Ô%5Ùð	(Üœ4 ›9×,Ñ,Ó.Ó/×5Ñ5Ó7ˆHð ×%Ñ% kÓ2ˆÜ�4—8‘8˜FÓ#×5Ð5¤t¨C£y§~¡~Ó6ˆØ—:‘:“<ˆß˜8×.Ñ.Ð/A×BÒBÀhÐRuÔFuÚÜ'¨Ó-ˆØ!×'Ñ'Ó)ˆ÷ �k [Ô0Ø ×,°+ÀÔ2LÔP[Ð\`ÓPa×PlÑPlÐmx×PyÕPyà�N‰NœC ›H d¨KÐ8×9ñ3 ð4 €Nøô9 ô ØŠ	ðûô
 ô 	Ûð	ûô œÐ$ô 	(Ü˜3“x—~‘~Ó'‹Hð	(ús6   ÃI ÃI0Ä*0JÉI-É,I-É0J É?J Ê*J1Ê0J1c                ó$   € V ^8„  d   QhR\         /# r*   r   )r   s   "r   r   r   Ê   s   € ÷ ñ œñ r   c                ó  €  \        V P                  4       ;'       g    R4      P                  4       P                  \        P
                  4      \        P
                  ,           #   \         d    \        P
                  u # i ; i)zWLower-cased cwd of *proc* with one trailing separator; bare ``os.sep`` when unreadable.r{   )r   Úcwdrƒ   r„   rH   r…   r   r~   s   &r   r©   r©   Ê   sY   € ðÜ�4—8‘8“:×#Ð# Ó$×*Ñ*Ó,×3Ñ3´B·F±FÓ;¼b¿f¹fÕDÐDøÜô Ü�v‰vŠðús   ‚A% žAA% Á%BÂBc                ó$   € V ^8„  d   QhR\         /# r*   )Ú	frozenset)r   s   "r   r   r   Ù   s   € ÷ %ñ %œYñ %r   c                 óP  € \         e   \         # 0 Rmp  ^ RIHp V! 4       ^ ,          P                   FE  pVP                  '       g   K  VP
                  ^ 8w  g   K*  V P                  VP                  4       KG  	  \        V 4      s \         #   \         d    \        s  \         # i ; i)uí  Top-level CLI flags that consume a value, from the REAL parser (nargs != 0); cached per process.

Derived so the holder classifier can't drift from argparse (a handwritten subset misparsed ``--reasoning high
serve``). Pre-argparse profile selectors are added explicitly (stripped before argparse sees argv). Falls back
to a static snapshot when the parser can't import â€” the updater must classify holders even on a broken tree.

Introspects ``build_top_level_parser()`` (every option with nargs != 0) so the holder classifier can
never drift from the argparse surface (#91869 review: a handwritten subset misparsed ``--reasoning high
serve`` as subcommand ``high`` and ``-m dashboard serve`` as ``dashboard`` â€” recreating the wrong-hint
class).
)Úbuild_top_level_parser>   ú-pú--configú	--profile)
Ú_holder_value_flags_cacheÚhermes_cli._parserr¼   Ú_actionsÚoption_stringsÚnargsÚupdaterº   r   Ú_HOLDER_VALUE_FLAGS_FALLBACK)Úflagsr¼   Úactions      r   Ú_holder_value_flagsrÉ   Ù   s“   € ô !Ò,Ü(Ð(Ú5€EðAÝ=Ù,Ó.¨qÕ1×:Ô:ˆFØ×$×$Ò$¨¯©¸Ö):Ø—‘˜V×2Ñ2Ö3ñ ;ô %.¨eÓ$4Ð!ô %Ð$øô ô AÜ$@Ñ!Ü$Ð$ðAús   ”0B Á	B Á*B ÂB%Â$B%c                ó>   € V ^8„  d   QhR\         R\         R,          /# ©r   r}   r&   Nr   )r   s   "r   r   r   ô   s   € ÷ )ñ )¤sð )¬s°T­zñ )r   c                ó¸  a	a
€  \         P                  ! V RR7      o
^ RIHpHp S
 Uu. uF#  q3P                  R4      P                  RR4      NK%  	  ppV! V4      '       d   V! V4      o
S
f   R# R V
3R	 llo	\        V	3R
 l\        S
4       4       R4      pVf   R# \        4       pV^,           pV\        S
4      8  dt   S
V,          pW†9   g   VP                  R^4      ^ ,          V9   d   TRV9   d   ^M^,          pKQ  VP                  R4      '       d   V^,          pKs  VP                  4       # R#   \         d    T P                  4       o
 EL7i ; iu upi )a¡  The actual Hermes SUBCOMMAND a venv-holder argv runs, or None (callers must NOT guess a label).

Token-based, never substring (``kanban --preserve-cache`` contains "serve"): find the ``hermes_cli.main`` /
``hermes(.exe)`` entry token, return the first following token that isn't a flag or a flag's value.

Profile selectors (``--profile X``, ``-p X``) are skipped like the canonical gateway matcher does. See
#90778.
F)Úposix)Úcommand_line_runs_inline_sourceÚinline_bootstrap_argvú"'Ú\Ú/Nc                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   ÚiÚtokenr&   )r9   r   r:   )r   s   "r   r   Ú/_hermes_holder_subcommand.<locals>.__annotate__  s&   € ÷ fñ f”Sð f¤ð f¬ñ fr   c                 óN  <€ VP                  4       P                  R 4      P                  RR4      pVP                  R4      ;'       d)    V ^ 8„  ;'       d    SV ^,
          ,          R8H  ;'       g6    VP	                  R^4      R,          R9   ;'       g    VP                  R4      # )rÐ   rÑ   rÒ   r›   ú-mzhermes_cli/main.pyéÿÿÿÿ)Úhermesr    )rƒ   ÚstripÚreplaceÚendswithÚrsplit)rÔ   rÕ   ÚlowÚtokenss   && €r   Ú	_is_entryÚ,_hermes_holder_subcommand.<locals>._is_entry  s˜   ø€ Ø�k‰k‹m×!Ñ! %Ó(×0Ñ0°°sÓ;ˆØ—‘Ð.Ó/×SÐS°A¸±E×SÐS¸fÀQÈÅU½mÈtÑ>S÷ fð fØ�J‰J�s˜AÓ˜rÕ"Ð&>Ñ>÷fð fØCFÇ<Á<ÐPdÓCeð	fr   c              3   óL   <"  € T F  w  rS! W4      '       g   K  Vx € K  	  R # 5irb   rc   )Ú.0rÔ   rÕ   rá   s   &  €r   Ú	<genexpr>Ú,_hermes_holder_subcommand.<locals>.<genexpr>  s   øé € ÐQÑ(9™H˜A¹YÀq×=P—a’aÓ(9ùs   ƒ$š
$Ú=Ú-)ÚshlexÚsplitr   Úgateway.status_inline_sourcerÎ   rÏ   rÛ   rÜ   ÚnextÚ	enumeraterÉ   Úlenr¨   rƒ   )r}   rÎ   rÏ   ÚtÚ
normalizedÚ	entry_idxÚvalue_flagsrÔ   rÕ   rá   rà   s   &        @@r   Ú_hermes_holder_subcommandró   ô   s/  ù€ ð!Ü—’˜W¨EÔ2ˆ÷ dÙ=CÓD¹V¸—'‘'˜%“.×(Ñ(¨¨sÖ3¹V€JÐDÙ& z×2Ò2Ù& zÓ2ˆØŠ>Ù÷fð fô
 ÔQ¬	°&Ô(9ÓQÐSWÓX€IØÒÙÜ%Ó'€KØ�A�€AØ
Œc�&‹kŒ/Ø�q•	ˆØÔ 5§;¡;¨s°AÓ#6°qÕ#9¸[Ô#HØ�c˜U”l‘¨Õ)ŠAØ×Ñ˜c×"Ò"Ø��FŠAà—;‘;“=Ð Ùøô= ô !Ø—‘“‹ð!üò Es   „D5 ¨)EÄ5EÅEc                ó\   € V ^8„  d   QhR\         \        ,          R\         \        ,          /# )r   rP   r&   ©rR   r9   )r   s   "r   r   r      s"   € ÷ ñ ¤4¬¥9ð ´´cµñ r   c                ó  € ^ RI Hp \        4       pV! 4       P                  4       '       d   V '       d   Vf   . # ^ RIHp V! V! 4       P                  4      ;'       g    V! 4       P                  R,          p\        V4      p\        V4      \        V 4      ,          p. pV  FÉ  p\        \        4      ;_uu_ 4        VP                  \        V4      4      P                  4       p	V	f    RRR4       KR  \        V	P                  4      p
W¦9  dU   W§9  dO   V	P!                  4       ;'       g    RP#                  4       P%                  V4      '       d   VP'                  V
4       RRR4       KË  	  V#   + '       g   i     Kà  ; i)a�  Venv-interpreter parents of *pids* that hold the install open; never raises.

A shim-started gateway is a chain: ``venv\Scripts\python.exe`` launcher (keeps ``.pyd`` mapped) -> uv
CPython worker (writes the PID file). The pause set sees the worker, the venv scan sees the launcher, so a
paused gateway still tripped the guard. One hop up only, venv-prefixed only (bounds blast radius).r”   Nr–   r˜   r{   )r¡   r•   r‰   r¢   r£   r—   r¤   r‡   rw   rT   r   r   rn   r9   rŒ   r5   r™   rƒ   r¨   rª   )rP   r•   rr   r—   r«   r¬   rt   Úfoundr5   rŒ   Úppids   &          r   Ú_venv_launcher_ancestorsrù      s  € õ )Ü‹Y€FÙ‹4×Ñ×Ò§T¨Vª^Øˆ	Ý1Ù¡£× 1Ñ 1Ó2×PÐP±b³d×6GÑ6GÈ&Õ6P€HÜ# HÓ-€KÜ.¨vÓ6¼¸T»ÕB€DØ€EÛˆÜ”i× Õ Ø—^‘^¤C¨£HÓ-×4Ñ4Ó6ˆFØŠ~Ø÷ !Ñ ô �v—z‘z“?ˆDØÔ DÔ$5¸6¿:¹:»<×;MÐ;MÈ2×:TÑ:TÓ:V×:aÑ:aÐbm×:nÒ:nØ—‘˜TÔ"÷ !Ñ ñ ð €L÷ !× Ð ús   Â;.E0Ã37E0Ä+%E0ÅE0Å0Fc                ó0   € V ^8„  d   QhR\         R\         /# ©r   r}   r&   r   )r   s   "r   r   r   :  s   € ÷ ñ œsð ¤sñ r   c                ó|   € ^ RI Hp V! V 4      '       d   R# \        V 4      pV\        9   d   R# V'       d   RV 2# R# )av  Machine-readable class of one venv holder for ``--list-venv-holders``.

``gateway`` (the pausable gateway matcher), ``backend`` (``serve``/``dashboard`` -- the Desktop
app's backend shape), ``hermes:<subcommand>`` for any other Hermes entry, else ``python``.
Derived from the same classifiers the refusal path uses so automation stops exactly what the
guard would refuse on.©Ú_is_pausable_gatewayÚgatewayÚbackendzhermes:rœ   )Úhermes_cli._scan_venv_blockersrþ   ró   Ú_BACKEND_PURPOSES)r}   rþ   Ú
subcommands   &  r   Ú_venv_holder_kindr  :  s?   € õ DÙ˜G×$Ò$ÙÜ*¨7Ó3€JØÔ&Ô&ÙßØ˜˜Ð%Ð%Ùr   c                ó:   € V ^8„  d   QhR\         \        ,          /# r*   )rR   r,   )r   s   "r   r   r   O  s   € ÷ ñ œ4¤�:ñ r   c                 óê  € ^ RI Hp  \        4       p. pV ! 4       P                  4        F´  w  r4pYErvVe~   \	        \
        4      ;_uu_ 4        VP                  \        V4      4      pVP                  4       ;'       g    TpRP                  VP                  4       4      ;'       g    TpRRR4       VP                  R\        V4      RVRVR\        V4      /4       K¶  	  V#   + '       g   i     LA; i)a  ``[{pid, exe, argv, kind}]`` for every process the venv-holder guard would refuse on, read-only.

Off Windows (or without psutil) the guard never fires, so the list is empty. ``exe``/``argv`` are the
live psutil values when readable (the scan may carry only a cmdline prefix).r”   Nrz   r5   r™   ÚargvÚkind)r¡   r•   r‰   rµ   r   r   rn   r9   r™   r|   r}   rª   r  )	r•   rr   Úholdersr5   rš   r}   r™   r  r   s	            r   Úlist_venv_holdersr
  O  sÄ   € õ
 )Ü‹Y€FØ€GÙ ›d×@Ñ@ÖBÑˆ�7ØˆTØÒÜœ)×$Õ$Ø—~‘~¤c¨#£hÓ/�Ø—h‘h“j×(Ð( D�Ø—x‘x §¡£Ó/×:Ð:°7�÷ %ð 	�‰˜œs 3›x¨°°V¸TÀ6ÔK\Ð]aÓKbÐcÖdñ Cð €N÷ %×$ús   ÁAC"Â&C"Ã"C2c                ó–   € V ^8„  d   QhR\         \        \        \        \        3,          ,          R\         \        ,          R,          /# ©r   r®   r&   N©rR   r’   r9   r   )r   s   "r   r   r   b  s5   € ÷ ñ ¬T´%¼¼SÄ#¸Õ2FÕ-Gð ÌDÔQTÍIÐX\ÕL\ñ r   c           
     óŒ  € ^ RI Hp \        4       p. pV  F˜  w  rEpTpVeb   \        \        4      ;_uu_ 4        RP                  VP                  \        V4      4      P                  4       4      ;'       g    TpRRR4       V! V4      '       g    R# VP                  \        V4      4       Kš  	  V#   + '       g   i     LA; i)a–  PIDs from *matches* when EVERY remaining venv holder is a pausable gateway, else ``None`` (keep refusing).

A gateway respawned inside the pause->guard window (or via an unmapped spawn path) still holds ``.pyd`` files.
Uses the Desktop preflight's ``_is_pausable_gateway`` so exemption and tolerance cannot drift; live argv is
re-read via psutil when possible since the scan may hold only a cmdline prefix.rý   Nrz   )
r  rþ   r‰   r   r   r|   rn   r9   r}   rª   )r®   rþ   rr   rP   r5   Ú_namer}   r  s   &       r   Ú_leftover_pausable_gateway_pidsr  b  s˜   € õ DÜ‹Y€FØ€DÛ&Ñˆ�GØˆØÒÜœ)×$Õ$Ø—x‘x §¡¬s°3«xÓ 8× @Ñ @Ó BÓC×NÐNÀw�÷ %á# D×)Ò)ÚØ�‰”C˜“HÖñ  'ð €K÷ %×$ús   ¸AB3Â3Cc                óR   € V ^8„  d   QhR\         \        ,          R\        R\        /# )r   rP   Úgateway_moder&   )rR   r9   r:   )r   s   "r   r   r   v  s&   € ÷ ñ ¬T´#­Yð Ìð ÔRVñ r   c               ó®   a € V'       g	   S '       g   R# V 3R lp\        VR4      pV'       g   R# \        RRP                  R V 4       4       R24       R# )	aè  Refuse a plain Windows update that would tree-kill its own ancestry (a chat agent's ``hermes update`` is
a gateway child; ``taskkill /T /F`` kills the updater first). ``--gateway`` is exempt (detached delivery).
Refuse only when a nominated gateway is positively an ancestor; unknown ancestry keeps existing recovery.

The leftover holder recovery below uses ``taskkill /T /F`` on Windows, so force-stopping that gateway
also kills the updater before it can mutate the checkout (#98814).
Fc                  ó€   <€ ^ RI Hp  S Uu. uF&  q! \        V4      4      '       g   K  \        V4      NK(  	  up# u upi )é    )Ú#_is_pid_ancestor_of_current_process)Úhermes_cli.gatewayr  r9   )r  r5   rP   s     €r   Ú
_ancestorsÚ6_refuse_gateway_ancestor_tree_kill.<locals>._ancestors€  s3   ø€ ÝJÙ$(ÓZ¡D˜SÐ,OÔPSÐTWÓPX×,Y””�C–¡DÑZÐZùÒZs   Œ;©;z7Could not inspect gateway ancestry before tree-kill: %sui   âœ— Refusing to stop the gateway process tree because this updater is running inside it (gateway PID(s): ú, c              3   ó8   "  € T F  p\        V4      x € K  	  R # 5irb   r   )rä   r5   s   & r   rå   Ú5_refuse_gateway_ancestor_tree_kill.<locals>.<genexpr>‰  s   é € Ð:YÉyÈ¼3¸s¿8¸8Ëyùs   ‚z½).
  On Windows, taskkill /T would terminate the updater before the update can run.
  From a chat platform, use `/update` instead.
  Otherwise, run `hermes update` from a separate terminal.T)r   Úprintr|   )rP   r  r  Ú	ancestorss   f$  r   Ú"_refuse_gateway_ancestor_tree_killr  v  s\   ø€ ÷ Ÿ4Ùõ[ô ˜*Ð&_Ó`€IßÙÜ	ð	1Ø15·±Ñ:YÉyÓ:YÓ1YÐ0Zð [uð	uôñ r   c                óˆ   € V ^8„  d   QhR\         \        \        \        \        3,          ,          R\         \        ,          /# ©r   r®   r&   )rR   r’   r9   r   r,   )r   s   "r   r   r   �  s.   € ÷ ñ ¬$¬u´S¼#¼s°]Õ/CÕ*Dð ÌÌdÍñ r   c                ó„  €  ^ RI HpHp T  UUUu0 uF  w  r4p\	        T4      kK  	  ppppT! 4        Uu. uFf  pTP                  R4      \        9   g   K  \        TP                  R4      \        4      '       g   KF  TR,          T9   g   KV  T! T4      RJg   Kd  TNKh  	  up#   \         d    . u # i ; iu upppi u upi )uŠ  Full ledger entries for venv holders that are MANUAL serve/dashboard backends.

Positive identity only: self-registered purpose serve/dashboard, live (pid, create_time), recorded spawner
NOT alive (a Desktop-owned backend keeps its live Electron spawner and must keep the refusal â€” the app would
respawn what we kill). Full entries let the relauncher rebuild from host/port/profile, not argv.©Úledger_entriesÚspawner_is_deadÚpurposer5   F)Úhermes_cli.process_identityr$  r%  r   r9   r0   r  Ú
isinstance)r®   r$  r%  r5   r  Ú_cmdÚholder_pidsÚentrys   &       r   Ú_ledger_manual_serve_holdersr,  �  s¼   € ðßOñ 5<Õ<±GÑ 0 ¨D”3�s–8±G€KÒ<á)Ô+óÙ+�%Ø�9‰9�YÓÔ#4Ñ4ô 	Ü9CÀEÇIÁIÈeÓDTÔVY×9Zô 	Ø_dÐejÕ_kÐozÑ_zô 	á˜EÓ"¨%Ð/÷ 	ˆÑ+ñð øô ô ØŠ	ðüä<ùòs3   ‚B# �B6´B=Á"B=Á<B=Â	B=ÂB=Â#B3Â2B3c                ór   € V ^8„  d   QhR\         \        ,          R\         \         \        ,          ,          /# )r   Úentriesr&   )rR   r,   r   )r   s   "r   r   r   ¢  s&   € ÷ ñ ¤d¬4¥jð ´T¼$¼s½)µ_ñ r   c           	     óÄ  a€ ^ RI Hp Rp\        \        4      ;_uu_ 4        V! 4       P	                  4       oSe   \        V3R lR 4       V4      pRRR4       . pV  Fë  pVP                  R4      p\        V\        4      '       d   V^ 8:  d   K3  \        VP                  R4      ;'       g    R4      \        VP                  R4      ;'       g    R4      rvTP                  V.V'       d   VR	8w  d   R
V.M. ,           \        VP                  R4      4      .,           V'       d   RV.M. ,           R\        V4      .,           4       Kí  	  V#   + '       g   i     EL; i)u¾   Rebuild launch commands for stopped serves from ledger host/port/profile â€” never argv parsing
(joined argv cannot round-trip Windows paths with spaces). Entries without a port are skipped.r”   rÚ   Nc              3   ó†   <"  € T F6  pSV,          P                  4       '       g   K"  \        SV,          4      x € K8  	  R # 5irb   )Úis_filer   )rä   ÚnÚscripts_dirs   & €r   rå   Ú+_serve_relaunch_commands.<locals>.<genexpr>ª  s4   øé € ÐqÑ9Q°AÐVaÐdeÕVe×UnÑUn×UpÔ/œ3˜{¨Q�×/Ð/Ó9Qùs
   ƒA§AÚportÚprofiler{   Úhostr   r¿   r&  z--hostz--port)r    rÚ   )r¡   r•   r   r   Ú_venv_scripts_dirrì   r0   r(  r9   r   rª   )	r.  r•   rÚ   Úcommandsr+  r5  r6  r7  r3  s	   &       @r   Ú_serve_relaunch_commandsr:  ¢  s*  ø€ õ )Ø€FÜ	”)×	Õ	Ù“d×,Ñ,Ó.ˆØÒ"ÜÔqÑ9QÓqÐsyÓzˆF÷ 
ð !#€HÛˆØ�y‰y˜Ó ˆÜ˜$¤×$Ò$¨°¬	ÙÜ˜EŸI™I iÓ0×6Ð6°BÓ7¼¸U¿Y¹YÀvÓ=N×=TÐ=TÐRTÓ9U�Ø�‰ØˆH·'¸gÈÔ>R˜ gÑ.ÐXZÕ[Ü�5—9‘9˜YÓ'Ó(Ð)õ*ßAE¨h¸Ñ-=È2õOØRZÔ\_Ð`dÓ\eÐQfõgö	
ñ ð €O÷ 
×	Ð	ús   ¡0EÅE	c                ó(   € V ^8„  d   QhR\         RR/# ©r   rÕ   r&   Nr+   )r   s   "r   r   r   ¸  s   € ÷ ñ ¤Dð ¨Tñ r   c           
     ó  € ^ RI HpHp V P                  R4      '       g   R# RV R&   V P                  R4      ;'       g    . pV'       g   R# \	        V4      p\        V4      \        V4      ,
          p. pV'       d"   \        R4       V! 4       P                  V4      pV'       g	   V'       d   \        R4       T! RV'       * ;'       d    V'       * R	\        V4      \        V4      ,
           R
\        V4       RV 24       R# )z­Idempotent atexit relaunch of manual serves stopped by the venv guard.

`pending` flips False on first invocation so explicit call + atexit registration cannot double-spawn.)r•   Ú_record_update_stepÚpendingNFr.  u4     âŸ² Relaunching stopped serve/dashboard backend(s)u‚     âš  Some stopped backends could not be relaunched automatically; restart them manually (hermes serve --host <ip> --port <port>).Úserve_relaunchzrelaunched=z failed=z	 skipped=)r¡   r•   r>  r0   r:  rî   r  Ú_respawn_dashboard_processes)rÕ   r•   r>  r.  r9  ÚskippedÚfaileds   &      r   Ú_relaunch_stopped_servesrD  ¸  sÕ   € ÷ >Ø�9‰9�Y×ÒÙØ€Eˆ)ÑØ�i‰i˜	Ó"×(Ð( b€GßÙÜ'¨Ó0€HÜ�'‹lœS ›]Õ*€GØ€FßÜÐDÔEÙ“×2Ñ2°8Ó<ˆß—&Üð  Sô  	TÙØ˜fœ*×4Ð4¨W¬Ø
”c˜(“m¤c¨&£kÕ1Ð2°(¼3¸v»;¸-ÀyÐQXÐPYÐZör   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úargv_lowr&   ©r   r:   )r   s   "r   r   r   Ñ  s   € ÷ 7ñ 7œsð 7¤tñ 7r   c                ó   € \        V 4      # )uÅ  Whether an argv is a DESKTOP backend â€” feeds ``taskkill /T`` via ``_orphaned_desktop_backend_pids``.

Same predicate as ``_looks_like_desktop_control_plane``: ``-m hermes_cli.main`` entry shape (the
Desktop's only spawn shape, ``apps/desktop/electron/main.ts``) AND the canonical holder classifier says
``serve``/``dashboard``. A user-launched ``hermes.exe serve`` / ``hermes dashboard`` is NOT the
Desktop's: the guard refuses on it, never reaps it.
)Ú!_looks_like_desktop_control_plane)rF  s   &r   Ú_is_backend_argvrJ  Ñ  s   € ô -¨XÓ6Ð6r   c                ó>   € V ^8„  d   QhR\         R\         R,          /# rË   r   )r   s   "r   r   r   Ü  s   € ÷ 	ñ 	¬ð 	´°tµñ 	r   c                ó  € Tp RP                  V P                  \        V4      4      P                  4       4      ;'       g    TpVP                  4       #   T P                   d     R# \
         d     TP                  4       # i ; i)z_Current lower-cased argv of *pid* (falls back to the scanned *cmdline*); ``None`` if it exited.rz   N)r|   rn   r9   r}   ÚNoSuchProcessr   rƒ   )rr   r5   r}   r  s   &&& r   Ú_live_argv_lowrN  Ü  sw   € à€DðØ�x‰x˜Ÿ™¤s¨3£xÓ0×8Ñ8Ó:Ó;×FÐF¸wˆð
 �:‰:‹<Ðøð	 ×Ñô ÚÜô ØØ�:‰:‹<Ððús#   „=A ÁA ÁBÁ)BÁ2BÂBc                ó¸   € V ^8„  d   QhR\         \        \        \        \        3,          ,          R\         \        \        \        3,          ,          R,          /# r  r  )r   s   "r   r   r   è  sF   € ÷ Bñ B¬D´´s¼CÄ°}Õ1EÕ,Fð BÌ4ÔPUÔVYÔ[^ÐV^ÕP_ÕK`ÐcgÕKgñ Br   c                ól  € \        4       pVf   R# . p. pV  EF#  w  rEp\        WV4      pVf   K  \        V4      '       g   VP                  \	        V4      4       KF   VP                  \	        V4      4      p\        VP                  4       ^d,          4      p	 TP                  4       p
T
'       d   TP                  T
4      MRpTeW   TP                  4       '       dA   TP                  4       TP                  4       8:  d   TP                  \	        T4      4       EK  TP                  \	        T4      T	34       EK&  	  V UUu0 uF  w  rLVkK	  	  pppV F]  p V'       dO   YÑP                  V4      P                  4        Uu0 uF  p\	        VP                  4      kK  	  up,          '       g    R# K_  	  V#   TP                   d     EK·  \         d      R# i ; i  TP                   d     LÕ\         d      R# i ; iu uppi u upi   TP                   d     KÎ  \         d      R# i ; i)uÀ  ``(pid, start_time)`` roots from *matches* when every remaining holder is an ORPHANED backend, else ``None``.

Killing a Desktop-owned ``serve`` is futile (the app respawns it), but a straggler whose Desktop is gone
would dead-end the update with "Hermes is still running" and zero open windows. Qualifies only if cmdline
is a Hermes backend AND the parent is demonstrably gone (PID missing or reused). Tree-aware: holders inside
an accepted root's tree fold into it; only roots are returned (``taskkill /T`` reaps descendants). Any
live-parent backend, unjustified non-backend, unprovable case, or no psutil -> ``None``. Never raises.

The venv-holder guard refuses on the Desktop app's ``serve`` backend by design: while the Desktop is
open, killing its backend is futile (the app supervises and respawns it within seconds), so the user
must close the app. But in the GUI-updater handoff path the Desktop has *already exited* â€” by contract
it tree-kills its backends and waits for the venv shim before spawning hermes-setup, and the
update-in-progress marker parks any relaunched Desktop from spawning a fresh backend (#50238). A
``serve`` backend still holding the venv at that point is a straggler whose supervisor is gone: SIGTERM
raced its spawn, or it belongs to a crashed window. Nothing will respawn it, and refusing on it
dead-ends the update with "Hermes is still running" while the user stares at zero open windows (ryanc's
2026-08-09 01:59/02:17 failures).
N)r‰   rN  rJ  rª   r9   rn   ÚroundrŽ   rM  r   rø   r�   ro   r5   )r®   rr   Úrootsrd   r5   r  r}   rß   r   Úprocess_start_timerø   rŒ   Ú_start_timeÚroot_setÚas   &              r   Ú_orphaned_desktop_backend_pidsrW  è  s÷  € ô& ‹Y€FØ‚~Ùà#%€EØ€IÜ&Ñˆ�GÜ˜V¨'Ó2ˆØŠ;ÙÜ ×$Ò$Ø×ÑœS ›XÔ&Ùð	Ø—>‘>¤# c£(Ó+ˆDô "' t×'7Ñ'7Ó'9¸CÕ'?Ó!@Ðð
	Ø—9‘9“;ˆDß-1�V—^‘^ DÔ)°tˆFð Ò! f×&7Ñ&7×&9Ò&9¸f×>PÑ>PÓ>RÐVZ×VfÑVfÓVhÔ>hØ× Ñ ¤ S£Ô*Úð
 	�‰”c˜#“hÐ 2Ð3×4ñ;  'ñ@ -2Ô2©EÑ(˜“©E€HÑ2Ûˆð	ß 8Ç>Á>ÐRUÓCV×C^ÑC^ÔC`Ó.aÑC`¸a¬s°1·5±5®zÑC`Ñ.a×#aÔ#aÚñ $bñ ð €Løð; ×#Ñ#ô 	ÛÜô 	Ûð	ûð ×#Ñ#ô 	ÙÜô 	Ûð	üó
 3ùò /bøà×#Ñ#ô 	ÚÜô 	Ûð	ús~   Á:F9ÂG Â1,G Ã=G ÅHÅ)HÆHÆ!HÆ9GÇGÇGÇGÇ HÇ3HÇ<HÈHÈHÈH3È$H3È-H3È2H3c                óˆ   € V ^8„  d   QhR\         \        \        \        \        3,          ,          R\         \        ,          /# r!  r  )r   s   "r   r   r   -  s.   € ÷ ñ ¬4´´c¼3Ä°mÕ0DÕ+Eð Ì$ÌsÍ)ñ r   c           
     óÌ  €  ^ RI HpHpHp V! 4       pT Uu/ uF<  p\        TP                  R4      \        4      '       g   K*  TP                  R4      TbK>  	  ppT  UUU	u. uF[  w  rxp	TP                  \        T4      4      ;p
'       g   K*  T
P                  R4      T9   g   KB  T! T
4      RJ g   KP  \        T4      NK]  	  up	pp#   \         d    . u # i ; iu upi u up	ppi )a•  PIDs the spawn ledger positively identifies as orphaned backends; never raises.

Strongest rung (no PPID/cmdline inference): qualifies when ``(pid, create_time)`` matches a live ledger entry
(PID reuse can't forge it), purpose is a REAPABLE kind (never interactive), and the recorded SPAWNER is
provably dead. Safe in ANY context. Unlisted holders fall to later rungs and never disqualify identified ones.)ÚREAPABLE_PURPOSESr$  r%  r5   r&  T)r'  rZ  r$  r%  r   r(  r0   r9   )r®   rZ  r$  r%  r.  ÚeÚby_pidr5   r  Ú_cmdliner+  s   &          r   Ú_ledger_reapable_backend_pidsr^  -  sÔ   € ðßbÑbÙ Ó"ˆñ (/ÓP¡w !´*¸Q¿U¹UÀ5»\Ì3×2OŒoˆa�e‰e�E‹l˜AŠo¡w€FÐPá-4õÙ-4Ñ)�S Ø—Z‘Z¤ C£Ó)Ð)ˆEÓ)ô 	Ø/4¯y©y¸Ó/CÐGXÑ/Xô 	Ù]lÐmrÓ]sÐw{Ð]{ô 	ŒˆCŽ©Wóð øô ô ØŠ	ðüâPùôs4   ‚C —'CÁCÁ!'CÂCÂ%	CÂ3CÃCÃCc                ó–   € V ^8„  d   QhR\         \        \        \        \        3,          ,          R\         \        ,          R,          /# r  r  )r   s   "r   r   r   ?  s5   € ÷ ñ ¬D´´s¼CÄ°}Õ1EÕ,Fð Ì4ÔPSÍ9ÐW[ÕK[ñ r   c                óÖ   € \        4       pVf   R# . pV  FF  w  r4p\        WV4      pVf   K  \        V4      '       g    R# VP                  \	        V4      4       KH  	  T;'       g    R# )a¬  Backend PIDs safe to tree-reap during a GUI-updater hand-off, INCLUDING ones with a live parent; never raises.

The orphan-only rung bails on ANY live parent (mid-teardown Electron, launcher->worker chain) and hung a
hand-off. Inside the hand-off gate (marker + ``--gateway`` + no live ``hermes.exe`` shim) nothing legitimate
supervises a ``serve`` from this venv, so survivors are leaks. Any non-backend holder or no psutil ->
``None``. The CALLER must have confirmed the gate; outside it the stricter orphan-only path stands.

Any ``serve`` backend still holding the venv here is therefore a leak, live parent or not, and reaping
its tree is correct rather than a race. See #50238.
N)r‰   rN  rJ  rª   r9   )r®   rr   rR  r5   r  r}   rß   s   &      r   Ú_handoff_reapable_backend_pidsra  ?  sg   € ô ‹Y€FØ‚~ÙØ€EÛ&Ñˆ�GÜ˜V¨'Ó2ˆØŠ;ÙÜ ×$Ò$ÚØ�‰”S˜“XÖñ  'ð �=ˆ=�DÐr   c                óŒ   € V ^8„  d   QhR\         \        ,          \         \        \        \        3,          ,          ,          RR/# )r   rP   r&   N)rR   r9   r’   )r   s   "r   r   r   X  s4   € ÷ Iñ Iœd¤3�i¬$¬u´S¼#°X­Õ*?Õ?ð IÀDñ Ir   c           
     ó:  € ^ RI Hp ^ RIHpHp V  FÖ  p\        V\        4      '       d   TM\        V4      V! \        V4      4      3w  rV Vf   \        P                  RV4       KV  V! WVR7      '       g   \        P                  RV4       K}  \        P                  ! RR\        V4      R	R
.R\        P                  \        P                  \        P                  V! 4       R7       KØ  	  R#   \         d#   p\        P                  RYW4        Rp?EK  Rp?ii ; i)zÎForce-stop each PID with its full child tree (Windows); best effort, never raises.

``taskkill /T /F``: stopping only the parent can leave a ``.hermes-runtime`` child holding the install open.

See #70026.
©Úget_process_start_time)Úpid_is_hermesÚwindows_hide_flagsNz9Skipping taskkill of PID %s: process identity unavailable)Úexpected_start_timez1Skipping taskkill of non-Hermes or changed PID %sÚtaskkillz/PIDz/Tz/FF)ÚcheckÚstdoutÚstderrÚstdinÚcreationflagsz"Could not stop process tree %s: %s)rF   re  Úhermes_cli._subprocess_compatrf  rg  r(  r’   r9   r   r   Ú
subprocessÚrunr   ÚDEVNULLr   )rP   re  rf  rg  r+  r5   rh  r   s   &       r   Ú_stop_process_treesrs  X  sâ   € õ 6ßOÛˆÜ,6°u¼e×,DÒ,D¡5Ì3ÈuË:ÑWmÔnqÐrwÓnxÓWyÐJzÑ ˆð	IØ"Ò*Ü—‘ÐXÐZ]Ô^ÙÙ  ×NÓNÜ—‘ÐPÐRUÔVÙÜ�NŠNØ˜V¤S¨£X¨t°TÐ:À%Ü!×)Ñ)´*×2DÑ2DÌJ×L^ÑL^Ù0Ó2÷ó øô ô 	IÜ�L‰LÐ=¸s×HÓHûð	Iús%   ÁC-Á'%C-ÂAC-Ã-DÃ8DÄDc                ó0   € V ^8„  d   QhR\         R\        /# rû   rG  )r   s   "r   r   r   s  s   € ÷ tñ t¬sð t´tñ tr   c                óp   € RT ;'       g    RP                  4       9   ;'       d    \        V 4      \        9   # )uå  True for this-install ``hermes serve`` / ``hermes dashboard`` argv (Desktop control plane).

Not the messaging gateway â€” don't feed into ``looks_like_gateway_command_line``. Token-based via the
parser-derived classifier, never substring (``kanban --preserve-cache``, ``-m dashboard chat``).
Undeterminable subcommand is NOT a control plane.

See #92091.
A cmdline whose subcommand cannot be determined is NOT a control plane â€” callers must not guess
ownership. See #90778, #91869.
r›   r{   )rƒ   ró   r  )r}   s   &r   rI  rI  s  s3   € ð  § ¨B× 5Ñ 5Ó 7Ñ7×sÐsÔ<UÐV]Ó<^ÔbsÑ<sÐsr   c                ó$   € V ^8„  d   QhR\         /# r*   r`   )r   s   "r   r   r   �  s   € ÷ ñ ¬ñ r   c            
     ó’  a€ ^ RI Hp  \        R4      ;_uu_ 4        ^ RIHpHo \        ;QJ d$    V3R lV! 4        4       F  '       g   K   RM	  RM! V3R lV! 4        4       4      '       d    RRR4       R#  RRR4       \        4       p\        \        R4      ;'       g    .  Fv  w  r4p\        V4      '       g   K  Vf    R# \        \        4      ;_uu_ 4        \        VP                  \        V4      4      4      '       d    RRR4        R#  RRR4       Kx  	  R#   + '       g   i     L°; i  + '       g   i     K   ; i)	a   True when Desktop currently supervises this install's control plane (updater must not steal gateway start).

Not proof messaging is served: serve is the control plane, the gateway a detached sibling. Prefer the spawn
ledger; fall back to the venv-holder scan. An orphaned control plane (supervisor gone) does not count;
without psutil orphanhood is unprovable and a live control plane suffices.

See #76129, #92091.
r”   z)Desktop-lifecycle ledger probe failed: %sr#  c              3   óv   <"  € T F.  qP                  R 4      \        9   ;'       d    S! V4      RJ x € K0  	  R# 5i)r&  FN)r0   r  )rä   r[  r%  s   & €r   rå   Ú2_desktop_owns_gateway_lifecycle.<locals>.<genexpr>�  s6   øé € ÐoÑ^nÐYZ�u‰u�YÓÔ#4Ñ4×TÐT¹ÈÓ9KÈuÐ9TÔTÓ^nùs   ƒ"9¦9TFNz(Desktop-lifecycle holder scan failed: %s)r¡   r•   r   r'  r$  r%  Úanyr‰   r   rµ   rI  r   r   r�   rn   r9   )r•   r$  rr   r5   r  r}   r%  s         @r   Ú_desktop_owns_gateway_lifecycler{  �  sí   ø€ õ )Ü	ÐA×	BÕ	BßOß‹3ÔoÑ^lÔ^nÓo�3�3Š3ÔoÑ^lÔ^nÓo×oÒoØ÷ 
CÑ	Bào÷ 
Cô ‹Y€FÜ(Ô)FÐHrÓs×yÐyÐwyÒyÑˆ�GÜ0°×9Ò9ÙØŠ>ÚÜ”i× Õ Ü˜vŸ~™~¬c°#«hÓ7×8Ò8Ø÷ !Ò Ø8÷ !Ñ ñ  zñ ÷ 
C×	Bú÷ !× Ð ús#   ›-D"Á"D"Á.D"Ã+D5Ä"D2	Ä5Ec                ó$   € V ^8„  d   QhR\         /# )r   rš   r   )r   s   "r   r   r   ›  s   € ÷ 0ñ 0”sñ 0r   c                ó.   € ^ RI pWP                  V 4      3# )zd``(psutil, service)`` for the named SCM service (psutil imported here so tests can stub the module).N)rr   Úwin_service_get©rš   rr   s   & r   Ú_win_servicer€  ›  s   € ãØ×)Ñ)¨$Ó/Ð/Ð/r   c                ó@   € V ^8„  d   QhR\         R\         R\         RR/# )r   Úverbrš   Úsettled_statusr&   Nr   )r   s   "r   r   r   ¡  s.   € ÷ Wñ W”#ð WœSð W¼3ð WÀ4ñ Wr   c           
     ó:  € \         P                  ! RW.RRRR^
RR7      pVP                  ^ 8w  dk   VP                  4       V8w  dT   VP                  ;'       g    VP
                  P                  4       p\        T;'       g    RV  RVP                   24      hR	# R	# )
zl``sc.exe <verb> <name>``; a non-zero exit is only an error when SCM doesn't already report *settled_status*.zsc.exeTzutf-8rÜ   F)Úcapture_outputÚtextÚencodingÚerrorsrQ   rj  zsc.exe z failed with N)rp  rq  Ú
returncodeÚstatusrl  rk  rÛ   r"   )r‚  rš   Úservicerƒ  ÚresultÚdetails   &&&&  r   Ú_sc_exerŽ  ¡  s’   € ä�^Š^Ø	�4Ð¨t¸$ÈÐYbØ˜%ô€Fð ×Ñ˜AÔ '§.¡.Ó"2°nÔ"DØ—-‘-×0Ð0 6§=¡=×7Ñ7Ó9ˆÜ˜6×UÐU w¨t¨f°MÀ&×BSÑBSÐATÐ%UÓVÐVñ #EÑr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   r5   rŽ   r&   )r9   rS   r:   )r   s   "r   r   r   ¬  s!   € ÷ 	/ñ 	/¬Cð 	/¼eð 	/Ìñ 	/r   c                óÞ   €  \        V P                  V4      P                  4       4      p\        Y2,
          4      R8*  #   T P                  T P                  3 d     R# \
         d     R# i ; i)z˜Is the process with this exact ``(pid, create_time)`` identity still alive? AccessDenied/unknown reads
True (fail closed: the venv may still be locked).FTçü©ñÒMbP?)rS   rn   rŽ   rM  ÚZombieProcessr   Úabs)rr   r5   rŽ   Úcurrents   &&& r   Ú_original_process_is_aliver•  ¬  sh   € ðÜ˜Ÿ™ sÓ+×7Ñ7Ó9Ó:ˆô
 ˆwÕ$Ó%¨Ñ.Ð.øð	 × Ñ  &×"6Ñ"6Ð7ô ÚÜô Úðús   ‚(> ¾A,ÁA,Á'A,Á+A,c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   rQ   Úintervalr&   )rS   r:   )r   s   "r   r   r   ¸  s!   € ÷ ñ ¤Eð ´Uð ÄTñ r   c                óÀ   € \         P                  ! 4       V,           p\         P                  ! 4       V8  d(   V ! 4       '       d   R# \         P                  ! V4       KA  R# )zYPoll *condition* every *interval* seconds until true (True) or *timeout* elapses (False).TF)Ú_timeÚ	monotonicÚsleep)Ú	conditionrQ   r—  Údeadlines   &&& r   rh   rh   ¸  s;   € ä�ŠÓ  7Õ*€HÜ
�/Š/Ó
˜hÔ
&Ù�;Š;ÙÜ�Š�HÖÙr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   r5   Úlabelr&   )r9   r   rS   )r   s   "r   r   r   Â  s&   € ÷ dñ d¤cð d´#ð d¼%ñ dr   c                ó¬   €  \        V P                  \        V4      4      P                  4       4      #   \         d   p\        RT R24      ThRp?ii ; i)zM``create_time`` of *pid*; unreadable identity aborts the stop (RuntimeError).úWindows z, process identity is unavailable before stopN)rS   rn   r9   rŽ   r   r"   )rr   r5   rŸ  r   s   &&& r   Ú_process_create_timer¢  Â  sS   € ðdÜ�V—^‘^¤C¨£HÓ-×9Ñ9Ó;Ó<Ð<øÜô dÜ˜X e WÐ,XÐYÓZÐ`cÐcûðdús   ‚03 ³A¾AÁAc                ó(   € V ^8„  d   QhR\         RR/# )r   rš   r&   Nr   )r   s   "r   r   r   Ê  s   € ÷ Xñ X¬Sð XÐtxñ Xr   c                óR  € Ve{    \        VP                  4       4      \        VP                  4       ;'       g    ^ 4      reTR8w  d   \        RT RT 24      hT\        T^ ,          4      8w  d   \        RT R24      hRV3RV33 FR  w  r‰V	f   K  \        \        W	^ ,          V4      \        V	^,          4      ,
          4      R	8”  g   KE  \        R
V R24      h	  Ve€   Vez    V P                  \        V^ ,          4      4      P                  4        U
u0 uF  p
\        V
P                  4      kK  	  pp
\        T^ ,          4      T9  d   \        RT 24      hR# R# R#   \         d   p\        RT R24      ThRp?ii ; iu up
i   \         d   p\        R4      ThRp?ii ; i)zhRefuse to stop *name* unless SCM state, service/gateway process identities and ancestry all still match.NúWindows service z( SCM identity is unavailable before stopÚrunningz$ is not stably running before stop: z) SCM process identity changed before stopr‹  rÿ   r‘  r¡  z% process identity changed before stopz;Windows gateway ancestry is unavailable before service stopz.Windows gateway is no longer owned by service )r   rŠ  r9   r5   r   r"   r“  r¢  rS   rn   ro   )rr   rš   r‹  Úexpected_service_identityÚexpected_gateway_identityÚcurrent_statusÚcurrent_service_pidr   rŸ  ÚidentityrŒ   Úancestor_pidss   &&&&&       r   Ú_verify_service_identitiesr­  Ê  sÅ  € à Ò,ð	kÜ25°g·n±nÓ6FÓ2GÌÈWÏ[É[Ë]×M_ÐM_Ð^_ÓI`Ð/ð ˜YÔ&ÜÐ!1°$°Ð7[Ð\jÐ[kÐlÓmÐmØ¤#Ð&?ÀÕ&BÓ"CÔCÜÐ!1°$°Ð7`ÐaÓbÐbØ&Ð(AÐBÀYÐPiÐDjÓk‰ˆØÔ¤CÔ(<¸VÈaÅ[ÐRWÓ(XÔ[`ÐaiÐjkÕalÓ[mÕ(mÓ$nÐqvÖ$vÜ ¨%¨Ð0UÐVÓWÐWñ lð !Ò,Ð1JÒ1Vð	gØ;A¿>¹>Ì#ÐNgÐhiÕNjÓJkÓ;l×;tÑ;tÔ;vÓwÑ;v°œS §¡ž_Ñ;vˆMÐwô Ð(¨Õ+Ó,°MÔAÜÐ!OÐPTÈvÐVÓWÐWñ Bñ 2WÑ,øô ô 	kÜÐ!1°$°Ð7_Ð`ÓaÐgjÐjûð	küò xøÜô 	gÜÐ\Ó]ÐcfÐfûð	gúsF   †3E" ºE" Ã&1F
 ÄFÄ5F
 Å"FÅ-E=Å=FÆF
 Æ
F&ÆF!Æ!F&Úexpected_processesr§  r¨  rQ   g      >@c                óô   € V ^8„  d   QhR\         R\        \        \        \        3,          R3,          R\        \        \        3,          R,          R\        \        \        3,          R,          R\        RR/# )	r   rš   r®  .r§  Nr¨  rQ   r&   )r   r’   r9   rS   )r   s   "r   r   r   á  sy   € ÷ vñ vÜ
ðvÜ&+¬E´#´u°*Õ,=¸sÐ,BÕ&CðvÜejÔknÔpuÐkuÕevÐy}Õe}ðvä$¤S¬% ZÕ0°4Õ7ðväINðvð 
ñvr   c               ó8  aaaa€ \        V 4      w  oo\        SV SW#4       \        RV SR4       R VV3R llo\        VV3R lV4      '       d   R# SP	                  4       R8w  d   \        RV  RVR	 R
24      hS! 4       ;p'       d   \        RV  RV 24      hR# )u®   Stop one verified Windows service and wait until SCM reports it down.

Lingering matching-identity processes after SCM says stopped make venv mutation unsafe â€” fail closed.ÚstopÚstoppedc                ó:   € V ^8„  d   QhR\         \        ,          /# r*   rõ   )r   s   "r   r   Ú3_stop_windows_gateway_service.<locals>.__annotate__ì  s   € ÷ xñ x”Dœ•Iñ xr   c            	      ód   <€ S U Uu. uF  w  r\        SW4      '       g   K  V NK  	  upp # u upp i rb   )r•  )r5   rŽ   r®  rr   s     €€r   r]   Ú-_stop_windows_gateway_service.<locals>._aliveì  s.   ø€ Ù,>ÔwÑ,>Ñ(˜ÔB\Ð]cÐeh×Bv—�Ñ,>ÒwÐwùÓws   ‡,¢,c                  óR   <€ SP                  4       R 8H  ;'       d    S ! 4       '       * # )r²  ©rŠ  )r]   r‹  s   €€r   Ú<lambda>Ú/_stop_windows_gateway_service.<locals>.<lambda>ï  s    ø€ ˜7Ÿ>™>Ó+¨yÑ8×IÐIÁÃ¼\ÐIr   Nr¥  z did not stop within ú.0fzs; venv mutation unsafe.z. stopped but its process tree is still alive: )r€  r­  rŽ  rh   rŠ  r"   )	rš   r®  r§  r¨  rQ   Úalive_after_stopr]   rr   r‹  s	   &d$$$ @@@r   Ú_stop_windows_gateway_servicer½  á  s­   û€ ô # 4Ó(�O€FˆGÜ˜v t¨WÐ6OÔkÜˆF�D˜' 9Ô-÷xñ xô ÕIÈ7×SÒSÙØ‡~�~Ó˜9Ô$ÜÐ-¨d¨VÐ3HÈÐQTÈÐUmÐnÓoÐoÙ!›8Ð#ÐÖ#ÜÐ-¨d¨VÐ3aÐbrÐasÐtÓuÐuñ $r   c                ó4   € V ^8„  d   QhR\         R\        RR/# ©r   rš   rQ   r&   N©r   rS   )r   s   "r   r   r   ÷  s&   € ÷ Zñ Z¬ð Z¼%ð ZÈ4ñ Zr   c               óš   a€ \        V 4      ^,          o\        RV SR4       \        V3R lV4      '       g   \        RV  RVR R24      hR# )	zEStart one previously paused Windows service and verify it is running.Ústartr¦  c                  ó*   <€ S P                  4       R 8H  # )r¦  r¸  )r‹  s   €r   r¹  Ú0_start_windows_gateway_service.<locals>.<lambda>û  s   ø€ ˜wŸ~™~Ó/°9Ò<r   r¥  z did not start within r»  ÚsN)r€  rŽ  rh   r"   )rš   rQ   r‹  s   &$@r   Ú_start_windows_gateway_servicerÆ  ÷  sT   ø€ ä˜4Ó  Õ#€GÜˆG�T˜7 IÔ.ÜÔ<¸g×FÒFÜÐ-¨d¨VÐ3IÈ'ÐRUÈÐVWÐXÓYÐYñ Gr   g      N@c                ó4   € V ^8„  d   QhR\         R\        RR/# r¿  rÀ  )r   s   "r   r   r   ÿ  s&   € ÷ mñ m¬3ð m¼Eð mÈTñ mr   c               óš   a aa€ ^ RI Ho \        S 4      ^,          oR VV V3R llp\        W!4      '       g   \	        RS  RVR R24      hR# )	zBRestore a service after an uncertain stop, including STOP_PENDING.©rÆ  c                ó$   € V ^8„  d   QhR\         /# r*   r`   )r   s   "r   r   Ú6_restore_windows_gateway_service.<locals>.__annotate__  s   € ÷ 0ñ 0”dñ 0r   c                  óL   <€ SP                  4       p V R 8X  d	   S! S4       V R9   # )r²  )r¦  r²  r¸  )rŠ  rÆ  rš   r‹  s    €€€r   Ú_settledÚ2_restore_windows_gateway_service.<locals>._settled  s+   ø€ Ø—‘Ó!ˆØ�YÔÙ*¨4Ô0ØÐ/Ñ/Ð/r   r¥  z) did not reach a restorable state within r»  rÅ  N)r¡   rÆ  r€  rh   r"   )rš   rQ   rÍ  rÆ  r‹  s   f$ @@r   Ú _restore_windows_gateway_servicerÏ  ÿ  sS   ú€ åDÜ˜4Ó  Õ#€G÷0ò 0ô �x×)Ò)ÜÐ-¨d¨VÐ3\Ð]dÐehÐ\iÐijÐkÓlÐlñ *r   c                ó2   € V ^8„  d   QhR\         R,          /# ©r   r&   Nr+   )r   s   "r   r   r     s   € ÷ ñ ¤$¨¥+ñ r   c                 óØ  € ^ RI Hp  ^ RIHp \	        R4      ;_uu_ 4        VP                  4       '       g    RRR4       R# RRR/ R. R	. R
R/p\	        R4      ;_uu_ 4        V ! 4       '       dC   VP                  . R7      pVf)   \        P                  R4        RRR4       RRR4       R# W2R&   RRR4       VuuRRR4       #   + '       g   i     L; i  + '       g   i     R# ; i)u–  Pause token for the no-running-gateway case: cold-start after update when an autostart entry exists.

An installed autostart entry is an explicit "I want a gateway" signal; a gateway that died between
updates would otherwise stay down until next login (resume only relaunches what was running).
Desktop-owned lifecycle -> ``None`` (spawning ``gateway run`` beside Desktop races ports/state);
the skip is ownership, not liveness â€” except when the start attestation reports a vouched-for
gateway that died without a clean exit. The Desktop hand-off exits the app before the updater starts
and can kill the running gateway in those same seconds, so discovery finds no live PID to pause
(#109538) â€” the dead attestation is the only surviving "a gateway was up" evidence, and the Desktop
only restarts gateways it stopped itself (its hand-off script, after the update verifies; #119809).
Keep the plan, and record the attestation
*generation* that authorized it on the token: the marker is a mutable one-shot that any concurrent
``hermes gateway status``/``start`` consumes, so execution authorizes the spawn from the token and
consumes only that generation (#110020 review).©r{  ©Úgateway_windowszACould not check Windows gateway autostart state before update: %sNÚresume_neededTÚprofilesÚunmapped_pidsÚunmappedÚcold_start_if_installedzECould not check Desktop gateway-lifecycle ownership before update: %s©Úcurrent_pidszHSkipping Windows gateway cold-start plan: Desktop owns gateway lifecycleÚattested_generation)	r¡   r{  Ú
hermes_clirÕ  r   Úis_installedÚattested_death_generationr   r   )r{  rÕ  rÕ   Ú
generations       r   Ú_windows_cold_start_planrâ    s×   € õ FÝ*Ü	ÐY×	ZÕ	ZØ×+Ñ+×-Ò-Ø÷ 
[Ñ	Zð ! $¨
°B¸ÈÈZÐY[Ð]vÐx|Ð}ˆÜÐa×bÕbÙ.×0Ò0Ø,×FÑFÐTVÐFÓW�
ØÒ%Ü—L‘LÐ!kÔlØ÷ c÷	 
[Ñ	Zð 0:Ð+Ñ,÷ cð ÷ 
[Ò	Z÷ c×bú÷	 
[Ö	Zñ ús5    CÁCÁ!:C	ÂCÂ-C	Â1	CÃCÃCÃC)	c                   óB   a a€ ] tR tRt oRtV3R lV 3R lltRtVtV ;t# )ÚServicePauseFailedi.  zïA gateway service could not be stopped; ``rollback_failures`` lists what the in-line
rollback could not restart. Empty = everything stopped was restarted, so the pause is void;
otherwise its record must stay, since gateways are still down.c                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# )r   r�  Úrollback_failures)r   rR   )r   Ú__classdict__s   "€r   r   ÚServicePauseFailed.__annotate__3  s   ø€ ÷ 3ñ 3™sð 3±t¹Cµyñ 3r   c                ó2   <€ \         SV `  V4       W n        R # rb   )ÚsuperÚ__init__ræ  )Úselfr�  ræ  Ú	__class__s   &&&€r   rë  ÚServicePauseFailed.__init__3  s   ø€ Ü‰Ñ˜Ô Ø!2Ör   )ræ  )	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rë  Ú__static_attributes__Ú__classdictcell__Ú__classcell__)rí  rç  s   @@r   rä  rä  .  s   ù‡ € ñF÷3÷ 3ó 3r   rä  c                óH   € V ^8„  d   QhR\         R\         R\        R\         /# )r   rÕ   r×  rÙ  r&   ©r,   rR   )r   s   "r   r   r   8  s0   € ÷ %Eñ %E¼Tð %EÌTð %EÔ]að %EÔfjñ %Er   c                óæ  aa€ ^ RI HoHp . pRp V  F›  p\        VP                  4      pV! V\        \        VRR4      4      \        VP                  4      \        VP                  4      3\        VP                  4      \        VP                  4      3R7       VP                  V4       RpK�  	  V'       d—   SP                  V\        V4      . R7       V  Uu/ uFH  p\        VP                  4      V9   g   K  \        VP                  4      \        VP                   4      bKJ  	  upSR&   \#        RRP%                  V4      ,           4       S# u upi   \&         Ed   p	T'       d   T.M. \        \)        T4      4      ,           p
\*        P-                  T
4       Uu. uF  q»T3T3R	 ll3NK  	  Mu upi ppT'       g	   T'       d   TP                  R
T3R l34       . pT F<  w  rï T! 4        K    \&         d"   pTP                  T RT 24        Rp?K6  Rp?ii ; i	  RT;'       g    R RT	 2pT'       d    TRRP%                  T4      ,           ,          p\/        TT4      T	hRp	?	ii ; i)zùStop each SCM gateway service, recording them on *token*; roll everything back on failure.

Runs after every fallible ordinary-gateway step so a failure here restores the attempted
services AND the already-paused ordinary gateways before re-raising.)rÏ  r½  NÚdescendant_identities)r®  r§  r¨  )ÚservicesÚexpected_servicesÚrestarted_servicesÚservice_profilesu)     âœ“ Paused Windows gateway service(s): r  c                 ó   <€ S! V 4      # rb   rc   )r2  rÏ  s   &€r   r¹  Ú1_pause_windows_gateway_services.<locals>.<lambda>Q  s   ø€ Ñ>^Ð_`Ô>ar   zordinary gatewaysc                  ó   <€ \        S 4      # rb   )Ú%_resume_windows_gateways_after_update©rÕ   s   €r   r¹  r   S  s   ø€ Ô:_Ð`eÔ:fr   r!   z'Could not stop Windows gateway service Úunknownz; rollback failures: ú; rc   )r¡   rÏ  r½  r   rš   r’   r/   r9   Úservice_pidrS   Úservice_create_timeÚgateway_pidÚgateway_create_timerª   rÅ   rR   r6  r  r|   r   Úreversedr,   Úfromkeysrä  )Úservice_gatewaysrÕ   r×  rÙ  r½  Úpaused_servicesÚcurrent_service_namer‹  rÅ  r   Úrestore_namesr2  Úrollbackræ  rŸ  ÚrestoreÚrestore_excr�  rÏ  s   &f&&              @r   Ú_pause_windows_gateway_servicesr  8  sc  ù€ ÷
 fØ€OØÐðEÛ'ˆGÜ#& w§|¡|Ó#4Ð Ù)Ø$¼¼wÀwÐPgÐikÓ?lÓ9mÜ+.¨w×/BÑ/BÓ+CÄUÈ7×KfÑKfÓEgÐ*hÜ+.¨w×/BÑ/BÓ+CÄUÈ7×KfÑKfÓEgÐ*hõð
 ×"Ñ"Ð#7Ô8Ø#'Ò ñ (÷ Ø�L‰L /ÄTÈ/ÓEZÐoqˆLÔrÙN^ó  )BÑN^ÈÔbeÐfg×flÑflÓbmð  rAñ  cAÔ)D¬¨Q¯V©V«´c¸!¿)¹)³nÒ)DÑN^ñ  )BˆEÐ$Ñ%ÜÐ=ÀÇ	Á	È/Ó@ZÕZÔ[Øˆùò )Bøô õ Eß3GÐ.Ñ/ÈRÔSWÔX`ÐapÓXqÓSrÕrˆÜlp×lyÑlyð  {Hô  mIó  .Jñ  mIÐgh¸1Ö2aÓ.bò  mIùò  .Jˆð  .Jß—xØ�O‰OÐ0Ô2fÐgÔhØÐÛ&‰NˆEðDÙ–	øÜô DØ!×(Ñ(¨E¨7°"°[°MÐ)B×CÒCûðDúñ 'ð
 ;Ð;O×;\Ð;\ÐS\Ð:]Ð]_Ð`cÐ_dÐeˆßØÐ-°·	±	Ð:KÓ0LÕLÕLˆFÜ  Ð):Ó;ÀÐDûðEús~   �B(E Â9!E ÃEÃ;-EÄ((E ÅE ÅI0Å"=I+ÆF3Æ2I+Ç
 I+Ç+G4Ç2I+Ç4H Ç?HÈI+ÈH È I+È/I+È?,I+É+I0ÚkeepÚquietTc                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r   r  r&   )r:   rR   r9   )r   s   "r   r   r   `  s"   € ÷ Kñ K´ð KÄÄcÅñ Kr   c               ó4   € ^ RI Hp V! \        V 4      WR7      # )aR  *pids* whose live home this update owns, plus *keep* (PIDs mapped to this install's profile
PID files / services). The same home scope the POSIX fleet restart uses (#93349): a gateway of
another Hermes install, or one whose home cannot be read, is named (unless *quiet*) and left
running, never paused, force-killed or replayed (#124659).)Ú_scoped_manual_gateway_pids©r  r  )Úhermes_cli.update_cmd_fleetr  rR   )rP   r  r  r  s   &$$ r   Ú_owned_gateway_pidsr  `  s   € õ
 HÙ&¤t¨D£z¸ÔJÐJr   c                 ó�  € ^ RI Hp HpHp \	        R4      ;_uu_ 4        V! RR7      pV Uu/ uF  qDP
                  VbK  	  ppRRR4       \	        R4      ;_uu_ 4        V! XR7      pRRR4       X Uu0 uF  p\        VP                  4      kK  	  pp\	        R4      ;_uu_ 4        \        \        P                  . V ! RR	7      O\        X4      O\        V4      O4      \        V4      V,          R
R7      p	RRR4       XWhX	3# u upi   + '       g   i     LÏ; i  + '       g   i     L½; iu upi   + '       g   i     LE; i)z|``(profile_processes, service_gateways, service_gateway_pids, running_pids)`` for the pause; any indeterminate probe aborts.)Úfind_gateway_pidsÚfind_profile_gateway_processesÚfind_windows_gateway_servicesz.Could not map Windows gateway PIDs to profilesT)ÚstrictNz5Could not determine Windows gateway service ownership)r2   z5Could not discover Windows gateway PIDs before update©Úall_profilesFr  )r  r  r  r  r#   r5   r9   r  r  r,   r  ÚsortedrT   )
r  r  r  Úprofile_process_listr   r2   r  r‹  r3   r1   s
             r   Ú_discover_windows_gatewaysr%  i  s  € çsÑsÜ	ÐI×	JÕ	JÙ=ÀTÔJÐÙ8LÓMÑ8L°ŸX™X tš^Ñ8LÐÐM÷ 
Kô 
ÐP×	QÕ	QÙ8ÐK_Ô`Ð÷ 
RáDTÓUÑDT¸œC × 3Ñ 3Ö4ÑDTÐÐUÜ	ÐP×	QÕ	Qä*¬4¯=©=ØnÑ¨TÔ2Ðn´VÐ<MÓ5NÐnÔQWÐXlÓQmÐnó,
äÐ%Ó&Ð)=Õ=ÀUôLˆ÷ 
Rð
 Ð.ÀlÐRÐRùò N÷ 
K×	Jú÷ 
R×	QüâUß	Q×	Qús;   žD
¬DÁD
Á
DÁ4D0Â'AD5ÄD
Ä
D	ÄD-	Ä5E	c                óî  € / p. p. pV  EF5  pWr9   d   RMVP                  V4      pVf   K#  \        V4      V\        VP                  4      &   VP	                  \        V4      4       \        \        VP                  4      \        V4      4      p	V	'       d   Ve   V! \        V4      4        ^ RIH	p
 V
! \        VP                  4      4      pV'       di   VP                  R4      '       g   VP                  R4      '       d8   VP	                  V4       V	'       g   Ve   V! \        V4      4       EK,  EK/  EK2  EK5  EK8  	  WEV3#   \         d#   p\        P                  RY|4        Rp?EKf  Rp?ii ; i)aÆ  Marker + socket-first pause for every profile-mapped gateway; ``(profiles, mapped_pids, socket_acks)``.

Socket ACK = the gateway drains and exits by its own graceful path. No answer (older
gateway) -> the marker poll / force-kill ladder in the caller. ``on_request(pid)`` runs once the
request is issued (marker on disk, else a positive socket ACK) and before the socket call: from
then on a crash leaves that gateway owed while it drains, never before.N)Úpause_gateway_for_updateÚpausingÚalready_stoppingz+Socket pause unavailable for gateway %s: %s)r0   r9   r   r6  rª   rN   r
   r.   Úgateway.control_socketr'  r   r   r   )r1   r2   r3   Ú
on_requestr×  Úmapped_pidsÚsocket_acksr5   r   Ú	requestedr'  Úackr   s   &&&&         r   Ú_request_socket_pausesr0  z  s4  € ð  "€HØ€KØ €KÜˆØÔ2‰tÐ8I×8MÑ8MÈcÓ8RˆØŠ<ÙÜ&)¨#£hˆ”�T—\‘\Ó"Ñ#Ø×Ñœ3˜s›8Ô$Ü5´d¸4¿9¹9³oÄsÈ3ÃxÓPˆ	ß˜Ò/Ù”s˜3“xÔ ð	Rõ HÙ*¬4°·	±	«?Ó;ˆCß˜Ÿ™ 	×*Ò*¨c¯g©gÐ6H×.IÒ.IØ×"Ñ" 3Ô'ß  ZÒ%;Ùœs 3›x×(ò &<’yò /JŠsñ# ð.  +Ð-Ð-øô ô 	RÜ�L‰LÐFÈ×QÓQûð	Rús*   Â-?EÃ-EÄEÄEÅE4ÅE/Å/E4c                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r   r-  r&   )rR   r,   rS   )r   s   "r   r   r   ž  s   € ÷ ñ ¬¬T­
ð ´uñ r   c                ót  € ^ RI Hp  \        \        V! 4       4      R4      pV '       di   \        \        4      ;_uu_ 4        \        R V  4       4      p\        W#R,           4      pRRR4       \        R\        V 4       R\        V4       R24       V#   \         d    Rp L�i ; i  + '       g   i     LI; i)	z£Drain budget: configured restart drain (>= 1s), raised to a socket-paused gateway's declared
ACTIVE-TURN budget + teardown grace so it isn't force-killed mid-turn.)Ú_get_restart_drain_timeoutg      ð?g      $@c              3   ój   "  € T F)  p\        VP                  R 4      ;'       g    R4      x € K+  	  R# 5i)Údrain_timeoutrg   N)rS   r0   )rä   rV  s   & r   rå   Ú)_gateway_drain_timeout.<locals>.<genexpr>¨  s)   é € ÐUÉÀAœ5 §¡ Ó!7×!>Ð!>¸3×?Ð?Ëùs   ‚!3¤3Nu     â†’ z. gateway(s) ACKed socket pause; waiting up to zs for graceful exit)	r  r3  ri   rS   r   r   r  rî   r9   )r-  r3  r5  Údeclareds   &   r   Ú_gateway_drain_timeoutr8  ž  s¢   € õ >ðÜœEÑ"<Ó">Ó?ÀÓEˆ÷ Ü”i× Õ ÜÑUÉÓUÓUˆHÜ ¸$­Ó?ˆM÷ !ô 	�”s˜;Ó'Ð(Ð(VÔWZÐ[hÓWiÐVjÐj}Ð~ÔØÐøô ô ØŠðú÷ !× ús   ˆB Á%B'ÂB$Â#B$Â'B7	c                ó2   € V ^8„  d   QhR\         R,          /# rÑ  r+   )r   s   "r   r   r   ®  s   € ÷ D?ñ D?¬D°4­Kñ D?r   c                 ó	  aaa€ ^ RI Hp  V ! 4       P                  4       '       g   R# \        R4      ;_uu_ 4        ^ RIp^ RIHo RRR4       ^ RIHo \        R4      ;_uu_ 4        SP                  4       w  r#RRR4       \        4       w  rErgV'       g   \        XX4      # V Uu. uF  qˆV9  g   K  W†9  g   K  VNK  	  p	p^ RIHp
 ^ RIHp V Uu/ uF  p\        V4      V
! \        V4      4      bK   	  ppV	 Uu/ uF  p\        V4      V! \        V4      4      bK   	  ppRVP!                  4       9   d>   \#        R	R
P%                  R VP'                  4        4       4      ,           R,           4      hV	 Uu. uFZ  pR\        V4      R\)        \        V4      3V3R llR\        V4      4      RV\        V4      ,          RV\        V4      ,          /NK\  	  ppRRRT	RTRV Uu/ uF8  pW„9   g   K  W†9  g   K  \+        WH,          P,                  4      \        V4      bK:  	  upRV Uu/ uF%  p\+        V4      SP/                  V4      R,          bK'  	  up/oV'       dz   V Uu. uF  p\+        VP0                  4      NK  	  ppSP3                  T\5        V4      . V Uu/ uF,  p\+        VP0                  4      \+        VP,                  4      bK.  	  upR7       \        R4      ;_uu_ 4        SP7                  SXX4       SP9                  SV\;        WtV4      R7       RRR4       \=        WtWiVVV3R lVR7      pRRRVRV	RV/p\?        V4      VP!                  4        Uu0 uF  p\+        VP,                  4      kK  	  up,          V Uu0 uF  p\+        VP,                  4      kK  	  up,          p\A        VV4        \C        VVVV4      pSPK                  TSX4      #   + '       g   i     EL¦; i  + '       g   i     EL†; iu upi u upi u upi u upi u upi u upi u upi u upi   + '       g   i     EL; iu upi u upi   \D         d+   pTPF                  '       g   SPI                  SX4       h Rp?ii ; i)a}  Stop running Windows gateways before mutating the checkout or venv.

Scheduled/startup gateways run via pythonw.exe, invisible to the hermes.exe instance guard, yet keep files
locked during ``git``/``uv``. Stop only PIDs the gateway discovery code identifies. The paused set is on
disk (``update_pause_record``) before the first stop, with any set a killed earlier update orphaned.r”   Nz2Could not prepare Windows gateway pause for update)Ú_capture_gateway_argv©Úupdate_pause_recordz4Could not read the gateways an earlier update pausedrd  ©Úgateway_pid_homez;Could not prove the Hermes home of unmapped gateway PID(s) r  c              3   óH   "  € T F  w  rVe   K  \        V4      x € K  	  R # 5irb   r   )rä   ÚpÚhs   &  r   rå   Ú5_pause_windows_gateways_for_update.<locals>.<genexpr>Í  s   é € Ð&U¹-±$°!È1¤v¤s¨1§v v»-ùs   ‚"�"z; nothing was stoppedr5   r  c                 ó   <€ S! V 4      # rb   rc   )rA  r;  s   &€r   r¹  Ú4_pause_windows_gateways_for_update.<locals>.<lambda>Ï  s   ø€ Ñ?TÐUVÔ?Wr   z2Could not capture argv for unmapped gateway %s: %sr6   ÚctrÖ  TrØ  rÙ  r×  Ú
identities)rû  rü  rý  rþ  z0Could not record the gateways this update pauses)r4   c                 ó(   <€ SP                  SV 4      # rb   )Úmark_stop_sent)r5   ÚintendedÚpause_records   &€€r   r¹  rE  æ  s   ø€ ¸\×=XÑ=XÐYaÐcfÔ=gr   )r+  Úborn)&r¡   r•   r¢   r#   rF   r  r;  rÞ  r=  Úadopt_orphansr%  Ú_cold_start_pause_tokenre  Úhermes_cli.update_fleet_scoper?  r9   Úvaluesr"   r|   Úitemsr   r   r6  r«  rš   rÅ   rR   Úrecord_pauseÚmark_stop_requestedr7   Ú_stop_windows_gatewaysrT   Ú$_record_attested_cold_start_profilesr  rä  ræ  Úabandon_pauseÚfinish_pause)r•   rÿ   ÚadoptedÚclaimsr2   r  r3   r1   r5   rØ  re  r?  rL  ÚhomesrÙ  rÅ  Únamesr×  rÕ   rA  Úrunning_profilesr   r;  rJ  rK  s                         @@@r   Ú"_pause_windows_gateways_for_updater]  ®  sJ  ú€ õ )Ù‹4×Ñ×ÒÙÜ	ÐM×	NÕ	NÛÝ<÷ 
Oõ ?Ü	ÐO×	PÕ	PØ&×4Ñ4Ó6‰ˆ÷ 
QäNhÓNjÑKÐÐ)=ßÜ& w°Ó7Ð7Ù$0Óu¡L˜SÐ?PÑ4P”SÐUXÑUt—S�S¡L€MÐuÝ5Ý>ÙBNÓOÁ,¸3ŒC�‹HÑ,¬S°«XÓ6Ò6Á,€DÐOñ >KÓK¹]°cŒS�‹XÑ'¬¨C«Ó1Ò1¹]€EÐKØˆu�|‰|‹~ÔÜÐXØ!ŸY™YÑ&U¸%¿+¹+¼-Ó&UÓUõVØXoõpó qð 	qñ !ó	ñ !ˆCð 
”�C“˜&¤)´S¸³XÖ,WØ,`ÔbeÐfiÓbjó#là	�”s˜3“x• $¨¬S°«X­ó	8ñ !ð	 ð ð 	˜˜°¸zÈ8ØÉló VÉlÀsØÑ0ô CØ58Ñ5Tô C”SÐ*Õ/×7Ñ7Ó8¼#¸c»(ÒBÉlñ VàÉ\ÓZÉ\Àc”s˜3“x ×!6Ñ!6°sÓ!;¸DÕ!AÒAÉ\ÑZð	€H÷ Ù&6Ó7Ñ&6 ”�Q—V‘V–Ñ&6ˆÐ7Ø�‰ ¼$¸u»+ÐZ\ÙO_Ó)`ÑO_È!¬#¨a¯f©f«+´s¸1¿9¹9³~Ò*EÑO_Ñ)`ð 	ô 	bä	ÐK×	LÕ	LØ×!Ñ! (¨G°VÔ<ð 	×(Ñ(Ø�lÔ,AÀ,ÐcwÓ,xð 	)ô 	z÷ 
Mô & lÐG[ÐltÝ1gÐnrôt€Hà˜d J°¸/È=ÐZdÐfnÐo€Eô ˜8“}Ð@Q×@XÑ@XÔ@ZÓ'[Ñ@Z¸1¬¨A¯I©I®Ñ@ZÑ'[Õ[ñ  xHó  _Iñ  xHÐrsÔ_bÐcd×clÑclÖ_mñ  xHñ  _Iõ  IÐÜ(¨Ð0@ÔAðÜ/Ð0@À%ÈÐS[Ó\ˆð
 ×$Ñ$ U¨H°gÓ>Ð>÷w 
O×	NÐ	Nú÷ 
Q×	PÐ	Püò
 vùò Pùò LùòùòVùâZùò 8ùâ)`ß	L×	LÐ	Lüò (\ùò  _Iøô ô Ø×$×$Ð$Ø×&Ñ& x°Ô9Øûðús�   ºO"Á&O6Â&P
Â3P
Â;P
Ã$PÃ=$PÅ9A PÇ&PÇ3PÇ;)PÈ++P#É&P(Ê!2P-Ë.2P2Í#QÎQÏQ Ï"O3	Ï6P	Ð2Q	ÑRÑ%R Ò Rc                óX   € V ^8„  d   QhR\         R,          R\        R\         R,          /# )r   rX  NrY  r&   rø  )r   s   "r   r   r   õ  s.   € ÷ Añ A¤T¨D¥[ð A¼$ð AÄ4È$Å;ñ Ar   c                ó~  € ^ RI Hp \        4       pVe   TM	RRR/ R. R. /p\        V\	        4       4       VP                  R4      '       d   TMTpV f   Ve   VP                  V4      # R# Ve   TM	RRR/ R. R. /p\        R	4      ;_uu_ 4        VP                  W0V4      uuRRR4       #   + '       g   i     R# ; i)
zYNo gateway runs: the cold-start plan, plus any orphaned set adopted from a killed update.r<  NrÖ  Tr×  rØ  rÙ  Úcold_start_profilesz/Could not record the adopted paused-gateway set)	rÞ  r=  râ  rU  rT   r0   Ú
stamp_treer#   rR  )rX  rY  rK  rÕ   Úprobes   &&   r   rN  rN  õ  sÁ   € å>Ü$Ó&€Eð Ò&‰E¨_¸dÀJÐPRÐTcÐegÐisÐuwÐ,x€EÜ(¨´³Ô6Ø—Y‘YÐ4×5Ò5‰E¸5€EØ‚Ø16Ò1Bˆ|×&Ñ& uÓ-ÐLÈÐLØÒ&‰E¨_¸dÀJÐPRÐTcÐegÐisÐuwÐ,x€EÜ	ÐJ×	KÕ	KØ×(Ñ(¨¸Ó@÷ 
L×	K×	KÓ	Kús   ÂB+Â+B<	c                ó$   € V ^8„  d   QhR\         /# r*   r+   )r   s   "r   r   r     s   € ÷ &ñ &Ü:>ñ&r   c                ó6  € ^ RI HpHp ^ RIHp	 V  U
u. uF2  p
\        V
4      V9  g   K  \        V
4      V9   g   K'  \        V
4      NK4  	  pp
/ T;'       g    / P                  4        UUu/ uF  w  rÍ\        V4      VbK  	  uppCV U
u/ uF\  p
\        \        W,          R^ 4      ;'       g    ^ 4      ^ 8”  g   K0  V
\        \        W,          P                  4      ^d,          4      bK^  	  up
CpV	! 4       P                  V4      pTP                  V U
u/ uF0  p
\        V
4      V9  g   K  \        V
4      V! \        V
4      4      bK2  	  up
4       \        WW%R7      w  ppp\        R4       \        V4      pV	! 4       P!                  VVR7      p. p\#        \%        V4      P'                  V4      P'                  V4      4       Fs  p\)        \*        \,        \.        4      ;_uu_ 4        V! \        V4      RVP1                  \        V4      4      R7       VP3                  \        V4      4       R	R	R	4       Ku  	  V'       d'   \        R
RP5                  \#        V4      4       24       V'       d   \        R\7        V4       R24       V'       d^   \        R\7        V4       R24       \8        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       d   \        R4       V# u up
i u uppi u up
i u up
i   + '       g   i     EKS  ; i)aÅ  Socket-pause the mapped gateways, drain, then tree-kill survivors; the paused ``profiles``.
A force-killed process needs no stop record: dead, it is owed; alive, it was never stopped.

The kill is authorized by each process's birth as discovered (*born*, a mapped gateway's
strict PID-file identity first), never re-read after the drain: a PID that exited and was
reused meanwhile reads its replacement's own birth. No discovered birth refuses the kill.)re  Úterminate_pidr”   rŽ   )r+  uB   â†’ Stopping Windows gateway process(es) before updating Hermes...)rQ   T)Úforcerh  Nu!     âœ“ Paused gateway profile(s): r  u     â†’ Force-stopped z gateway process(es)u     â†’ Stopped z, gateway process(es) without profile mappingc              3   óL   "  € T F  qP                  R 4      '       * x € K  	  R# 5i©r  N©r0   ©rä   Úus   & r   rå   Ú)_stop_windows_gateways.<locals>.<genexpr>)  s   é € Ð3©( Q—5‘5˜“=× Ñ «(ùs   ‚"$Fz5    Restart manually after update: hermes gateway run)rF   re  re  r¡   r•   r9   rQ  rS   r/   rQ  rŽ   rù   rÅ   r0  r  r8  rj   r#  rT   Úunionr   ÚProcessLookupErrorrM   rL   r0   rª   r|   rî   rz  )r1   r2   r3   rØ  rÙ  r+  rL  re  re  r•   rA  ÚmappedÚkÚvÚlauncher_pidsr×  r,  r-  r5  Ú	survivorsÚforce_killedr5   s   &&&&&&&               r   rT  rT    s   € ÷ EÝ(Ù*Óq™l˜¬c°!«fÐ<PÑ.PŒfÔUXÐYZÓU[Ð_pÑUpŒfŒc�!Žf™l€FÐqðT d§j j¨b×%7Ñ%7Ô%9Ô:Ñ%9™T˜QŒs�1‹v�qŠyÑ%9Ò:ð TÙPVó SÑPVÈ1ÜœÐ 1Õ 4°mÀQÓG×LÐLÈ1ÓMÐPQÑQô Gˆq”%œÐ/Õ2×>Ñ>Ó?À#ÕEÓFÒFÑPVñ SðT€Dñ
 “D×1Ñ1°&Ó9€MØ‡K�KÁÓeÁ¸AÔRUÐVWÓRXÐ`dÑRdÔ7”�Q“Ñ/´°A³Ó7Ò7ÁÑeÔfÜ)?ØÐ)=ô*VÑ&€Hˆk˜;ä	Ð
NÔOÜ*¨;Ó7€MÙ“×:Ñ:¸;ÐP]Ð:Ó^€Ið €LÜ”c˜)“n×*Ñ*¨=Ó9×?Ñ?ÀÓNÖOˆÜÔ(¬/¼7×CÕCÙœ#˜c›(¨$ÀDÇHÁHÌSÐQTËXÓDVÕWØ×Ñ¤ C£Ô)÷ DÑCñ P÷ ÜÐ1°$·)±)¼FÀ8Ó<LÓ2MÐ1NÐOÔPßÜÐ$¤S¨Ó%6Ð$7Ð7KÐLÔMßÜ�œs =Ó1Ð2Ð2^Ð_Ô`ß‹3Ñ3©(Ó3�3�3Š3Ñ3©(Ó3×3Ò3ÜÐIÔJØ€Oùò9 rùÛ:ùòSùò
 f÷ D×CÑCús:   “K1ªK1¼K1Á+K6Â
-K<Â<0K<ÄLÄ,LÇ)ALÌLc                ó4   € V ^8„  d   QhR\         R\        RR/# )r   rÕ   r\  r&   N©r,   rT   )r   s   "r   r   r   .  s"   € ÷ 0ñ 0´ð 0Ìð 0ÐPTñ 0r   c           	     óÀ  € ^ RI Hp ^ RIHp \	        R4      ;_uu_ 4        V! 4       '       g    RRR4       R# ^ RIHpHp V! 4       ;'       g    Rp/ pV! RRR7       FT  w  r‰W�9   g   W†8X  d   V P                  R	4      '       d   K*  VP                  . \        V	4      R
7      p
V
'       g   KP  W§V&   KV  	  V'       d   WpR&   RRR4       R#   + '       g   i     R# ; i)aJ  Record ``token["cold_start_profiles"] = {name: generation}`` for every known profile that is not
running yet holds a start attestation for a gateway that died without a clean exit (#110959).

The all-or-nothing plan only ever probed the ACTIVE profile and only when NO gateway ran at all, so a
dead-but-attested default beside a still-running ``beta`` never got a cold-start obligation. Only
Desktop-owned installs need this (elsewhere autostart brings the profile back); the active profile is
left to the existing plan so it is never spawned twice. Best-effort: never blocks the pause.rÓ  rÔ  zECould not evaluate per-profile attested cold-starts before update: %sN)Úget_active_profile_nameÚprofiles_to_server   T)Ú	multiplexÚinclude_standalonerÚ  ©r6   r`  )r¡   r{  rÞ  rÕ  r   Úhermes_cli.profilesrx  ry  r0   rà  r
   )rÕ   r\  r{  rÕ  rx  ry  ÚactiveÚcoldrš   r6   rá  s   &&         r   rU  rU  .  s»   € õ FÝ*Ü	Ð]×	^Õ	^Ù.×0Ò0Ø÷ 
_Ñ	^÷ 	SÙ(Ó*×7Ð7¨iˆØ!ˆá+°dÈt×T‰JˆDØÔ'¨D¬N¸u¿y¹yÐIb×?cÒ?cÙØ(×BÑBÀ2ÌDÐQUËJÐBÓWˆJß‰zØ'�T“
ñ U÷ Ø+/Ð'Ñ(÷ 
_×	^×	^Ò	^ús(    C¹CÁ6CÂ#CÂ.CÂ>CÃC	c                ó(   € V ^8„  d   QhR\         RR/# r<  r+   )r   s   "r   r   r   I  s   € ÷ +ñ +¬ð +°$ñ +r   c           
     ór  € ^ RI Hp ^ RIHp \	        V P                  R4      ;'       g    / 4      pV'       g   R# \        VP                  4       4       Fø  w  rE\        V! V4      4      p\        RV R24      ;_uu_ 4        VP                  VR7      '       g&   VP                  VR7      pV'       g   \        R4      hVP                  VR7      pV'       g   \        R	V R
24      hVP                  WVR7       VP                  VRV R2VR7       \!        RV RV^ ,           R24       V R,          P#                  VR4       RRR4       Kú  	  V R,          '       d2   \        RRP%                  \        V R,          4      4      ,           4      hV P#                  RR4       R#   + '       g   i     EKb  ; i)z²Spawn each ``cold_start_profiles`` entry under its own HERMES_HOME and consume exactly the
generation that authorized it; one profile's failure never aborts the others (#110959).rÔ  ©Úget_profile_dirr`  Nz-Could not cold-start Windows gateway profile z after update: %sr|  z&cold-start did not return a process IDzgateway profile ú did not become readyz!cold-start after update (profile Ú)u   
âœ“ Gateway profile z+ started via cold-start after update (PID: z<Windows gateway cold-start was not verified for profile(s): r  )rÞ  rÕ  r}  rƒ  r,   r0   r#  rQ  r
   r   Ú_live_gateway_pidsÚ_spawn_detachedr"   Ú_wait_for_gateway_readyÚ_consume_start_attestationÚ_write_start_attestationr  Úpopr|   )	rÕ   rÕ  rƒ  r?  rš   rá  r6   r5   Ú
ready_pidss	   &        r   Ú_cold_start_attested_profilesr�  I  s›  € õ +Ý3Ü�5—9‘9Ð2Ó3×9Ð9°rÓ:€GßÙÜ" 7§=¡=£?Ö3ÑˆÜ‘O DÓ)Ó*ˆÜÐIÈ$ÈÐO`Ða×bÕbØ"×5Ñ5¸4Ð5×@Ò@Ø%×5Ñ5¸4Ð5Ó@�ßÜ&Ð'OÓPÐPØ(×@Ñ@ÀdÐ@ÓKˆJßÜ"Ð%5°d°VÐ;PÐ#QÓRÐRØ×6Ñ6°zÐ6ÔMà×4Ñ4°ZÐCdÐeiÐdjÐjkÐAlÐswÐ4ÔxÜÐ*¨4¨&Ð0[Ð\fÐghÕ\iÐ[jÐjkÐlÔmØÐ'Õ(×,Ñ,¨T°4Ô8÷ cÑbñ 4ð Ð"×#Ô#ô ÐYØ!ŸY™Y¤v¨eÐ4IÕ.JÓ'KÓLõMó Nð 	Nà	‡I�IÐ# TÖ*÷% c×bÑbús   Â2F$Â4$F$ÃA+F$Æ$F6c                ó>   € V ^8„  d   QhR\         R,          R\        /# ©r   rÕ   Nr&   )r,   r:   )r   s   "r   r   r   h  s   € ÷ 8ñ 8´D¸4µKð 8Ì4ñ 8r   c           	     ó  € ^ RI HpHp V! 4       P                  4       '       g   R# \	        R4      ;_uu_ 4        ^ RIHp ^ RIHp RRR4       \	        R4      ;_uu_ 4        \        X! RR7      4      '       d    RRR4       R#  RRR4       T ;'       g    / p V P                  R	4      pVf6   R	V 9  d/   \	        R
4      ;_uu_ 4        XP                  . R7      pRRR4       \	        R4      ;_uu_ 4        V! 4       '       d)   V'       g!   \        P                  R4        RRR4       R# RRR4       \	        R4      ;_uu_ 4        XP                  4       pRRR4       X'       g   \        R4      hXP!                  4       pV'       g   \        RV R24      hV'       d   VP#                  V4       \%        RRP'                  \)        \*        V4      4       R24       \-        \.        4      ;_uu_ 4        VP1                  VR4       RRR4       R#   + '       g   i     EL×; i  + '       g   i     EL«; i  + '       g   i     ELi; i  + '       g   i     EL,; i  + '       g   i     EL; i  + '       g   i     R# ; i)un  Direct-spawn a detached gateway after update for the ``cold_start_if_installed`` case (installed but down).

Idempotent: re-checks nothing is running so a concurrent autostart can't duplicate. A successful Popen
doesn't prove survival (a job object denying breakaway kills it), so success is gated on the liveness poll.
Vouched PIDs are attested so a death AFTER updater exit is reported by the next CLI invocation.

A successful ``Popen`` only proves the process was created, not that it survived (e.g. a Windows job
object denying breakaway kills it before it logs anything â€” #84185). So the success line is gated on the
same post-spawn liveness poll every other ``_spawn_detached`` caller uses
(``gateway_windows._report_gateway_start``), instead of being printed unconditionally from the returned
PID.

Desktop-owned lifecycle suppresses the spawn only while nothing attests a gateway is expected: an
attested gateway that died without a clean exit is restored even then (#109538) â€” the Desktop does
not restart the messaging gateway itself. That authority is the ``attested_generation`` the plan
recorded on ``token``, not the marker on disk: the marker is a mutable one-shot a concurrent
``hermes gateway status``/``start`` consumes, which would otherwise skip this spawn and clear the
token (#110020 review). Only that generation is consumed afterwards â€” never a newer marker.
)r{  r•   Tz1Could not load Windows gateway cold-start helpersrÔ  ©r  Nz5Could not re-check gateway liveness before cold-startr!  rÝ  z9Could not re-read the start attestation before cold-startrÛ  zHCould not re-check Desktop gateway-lifecycle ownership before cold-startzCSkipping Windows gateway cold-start: Desktop owns gateway lifecyclez1Could not cold-start Windows gateway after updatez6Windows gateway cold-start did not return a process IDzWindows gateway cold-start PID r„  u7   
âœ“ Gateway started via cold-start after update (PID: r  r…  zcold-start after update)r¡   r{  r•   r¢   r#   rÞ  rÕ  r  r  r  r0   rà  r   r   r‡  r"   rˆ  r‰  r  r|   Úmapr   r   r   rŠ  )rÕ   r{  r•   rÕ  r  rá  r5   rŒ  s   &       r   Ú(_cold_start_windows_gateway_after_updater“  h  së  € ÷( JÙ‹4×Ñ×ÒÙÜ	ÐL×	MÕ	MÝ.Ý8÷ 
Nô 
ÐP×	QÕ	QäÑ0¸dÔC×DÒDØ÷ 
RÑ	QàD÷ 
Rð �KˆK�R€EØ—‘Ð0Ó1€JØÒÐ3¸5Ô@äÐX×YÕYØ(×BÑBÐPRÐBÓSˆJ÷ Zä	Ðc×	dÕ	dÙ*×,Ò,·ZÜ�L‰LÐ^Ô_Ø÷ 
e×	dÑ	dô 
ÐL×	MÕ	MØ×-Ñ-Ó/ˆ÷ 
NçÜÐSÓTÐTØ ×8Ñ8Ó:€JßÜÐ<¸S¸EÐAVÐWÓXÐX÷
 Ø×2Ñ2°:Ô>Ü	ÐDÀTÇYÁYÌsÔSVÐXbÓOcÓEdÐDeÐefÐ
gÔhÜ	”)×	Õ	Ø×0Ñ0°Ð=VÔW÷ 
á÷C 
N×	MÐ	Mú÷ 
R×	QÐ	Qú÷ Z×YÐYúç	d×	dÐ	dú÷ 
N×	MÐ	Mú÷ 
Ö	áúsM   ¹HÁ!H(Ã	H<Ã7IÄIÅI$Ç7I8ÈH%	È(H9	È<I	ÉI!	É$I5	É8J		c                ó   € V ^8„  d   QhRR/# rÑ  rc   )r   s   "r   r   r   £  s   € ÷ Zñ Z¨Dñ Zr   c                 ó  € ^ RI Hp  V ! 4       P                  4       '       g   R# \        R4      ;_uu_ 4        ^ RIHp VP                  4       '       d‘   VP                  4        \        R4       VP                  4       w  r#V F  p\        RV 24       K  	  V F  p\        RV 24       K  	  VP                  4       '       d    VP                  VP                  4       4       RRR4       R#   + '       g   i     R# ; i)u  Regenerate installed Windows gateway launcher scripts after update; best-effort, never fails the update.

Launchers are written once at install, so old installs kept launching via ``pythonw.exe`` (``sys.stderr is
None`` death). The task's /TR points at a stable path, so rewriting in place retargets it without UAC.

The Scheduled Task / Startup-folder launchers (``gateway.cmd`` + ``gateway.vbs``) are persistence
artifacts written once at install time â€” ``hermes update`` never touched them, so installs created
before the hidden-console rework (aa2ae36c3f) kept launching the gateway through ``pythonw.exe``
forever: every descendant spawn flashed a conhost (#54220/#56747) and, since #70344, the console-less
gateway died at startup with ``RuntimeError: sys.stderr is None`` (#71671).
r”   Nz<Could not refresh Windows gateway launchers after update: %srÔ  u0     âœ“ Refreshed Windows gateway launcher scriptsu     âœ“ u     âš  )r¡   r•   r¢   r   rÞ  rÕ  rß  Ú_write_task_scriptr  Úreconcile_autostart_launchersÚis_task_registeredÚreconcile_scheduled_taskÚget_task_name)r•   rÕ  ÚdoneÚwarningsÚmessages        r   Ú"_refresh_windows_gateway_launchersrž  £  sÆ   € õ )Ù‹4×Ñ×ÒÙÜ	ÐT×	UÕ	UÝ.Ø×'Ñ'×)Ò)Ø×.Ñ.Ô0ÜÐDÔEà,×JÑJÓL‰NˆDÛ�Ü˜˜w˜iÐ(Ö)ñ  ã#�Ü˜˜w˜iÐ(Ö)ñ $à×1Ñ1×3Ò3à×8Ñ8¸×9VÑ9VÓ9XÔY÷ 
V×	U×	UÒ	Uús   ·BC.ÃC.Ã.C?	c                ó(   € V ^8„  d   QhR\         RR/# )r   Úbranchr&   Nr   )r   s   "r   r   r   Â  s   € ÷ +jñ +j¬Sð +j¸dñ +jr   c           
     óB  € ^ RI Hp \        R4      ;_uu_ 4        \        V! 4       P	                  4       4      R,          pVP                  4       '       g    RRR4       R# \        P                  ! RR\        T ;'       g    R4      4      p\        P                  ! RV4      '       d    RRR4       R# . pR EF  w  rVV! 4       P                  R
,          V,          pVRV RV 2,          pVP                  4       '       d   VP                  4       '       g   Kb  VP                  4       p	VR	8X  d!   V	P                  R4      '       g
   RV	,           p	VP                  4       V	8X  d   K°  VP                  VP                  R,           4      p
V
P!                  V	4       \"        P$                  ! W¨4       VP'                  VP(                  4       EK  	  V'       d+   \+        RRP-                  \/        V4      4      ,           4       RRR4       R#   + '       g   i     R# ; i)u2  Overwrite ``$HERMES_HOME/bootstrap-cache/install-<ref>.{ps1,sh}`` for *branch* from the fresh checkout.

Old ``hermes-setup.exe`` builds NEVER re-download a cached branch-ref script, so a stale one runs
months-old code forever. Guards mirror ``install_script.rs``: only the sanitized *branch* key is rewritten;
commit-SHA pins (7-40 hex) are immutable and skipped. Best-effort: never fails the update.

Installer binaries built before the #67193 cache-refresh fix (June 2026 and earlier) NEVER re-download a
cached branch-ref script â€” ``install-main.ps1`` cached at install time is reused forever, executing
months-stale code with long-fixed bugs (the 2026-08-09 incident: a June 4 cached script's venv stage
lacked the 81327 process-tree sweep and died on ``Access denied``). The binary has no self-update path,
so the poisoned cache outlives every ``hermes update``.
Overwriting the cached script for *branch* with the freshly pulled ``scripts/install.ps1`` /
``scripts/install.sh`` on every update turns the stale binary's unconditional reuse into a feature: it
"reuses" a file this function keeps permanently current. Post-#67193 installers re-download on each run
anyway, so for them this is a harmless pre-seed of the same bytes.
The .ps1 copy gets a UTF-8 BOM to match the installer's cache format (#67193 encoding fix).
r”   z:Could not refresh bootstrap-cache scripts after update: %szbootstrap-cacheNz[^A-Za-z0-9._-]Ú_Úmainz[0-9a-fA-F]{7,40}Úps1Úscriptszinstall-Ú.s   ï»¿z.tmpu5     âœ“ Refreshed installer bootstrap-cache script(s): r  ))r¤  zinstall.ps1)Úshz
install.sh)r¡   r•   r   r
   Úget_hermes_homeÚis_dirÚreÚsubr   Ú	fullmatchr¤   r1  Ú
read_bytesr¨   Úwith_suffixÚsuffixÚwrite_bytesrH   rÜ   rª   rš   r  r|   r#  )r   r•   Ú	cache_dirÚsafe_refÚ	refreshedr  Úsrc_nameÚsrcÚcachedÚdataÚtmps   &          r   Ú _refresh_bootstrap_cache_scriptsr¹  Â  sš  € õ$ )Ü	ÐR×	SÕ	SÜ™›×-Ñ-Ó/Ó0Ð3DÕDˆ	Ø×Ñ×!Ò!Ø÷ 
TÑ	Sô —6’6Ð,¨c´3°v×7GÐ7GÀÓ3HÓIˆÜ�<Š<Ð,¨h×7Ò7Ø÷ 
TÑ	Sð ˆ	ÜL‰NˆDÙ“$×#Ñ# iÕ/°(Õ:ˆCØ 8¨H¨:°Q°t°fÐ!=Õ=ˆFØ—;‘;—=’=¨¯©×(8Ò(8ÙØ—>‘>Ó#ˆDØ�uŒ} T§_¡_°_×%EÒ%EØ&¨Õ-�à× Ñ Ó" dÔ*ÙØ×$Ñ$ V§]¡]°VÕ%;Ó<ˆCØ�O‰O˜DÔ!Ü�JŠJ�sÔ#Ø×Ñ˜VŸ[™[×)ñ M÷ ÜÐIÈDÏIÉIÔV\Ð]fÓVgÓLhÕhÔi÷1 
T×	S×	SÒ	Sús7   š=HÁ!HÂ'HÂ)HÂ4A#HÄ/HÅBHÇ*HÈH	g      @g      ¬@c          	      óz   € V ^8„  d   QhR\         R\         R,          R\        R,          R\        \        ,          /# )r   rš   r6  NÚ	timeout_sr&   )r   rS   rR   r9   )r   s   "r   r   r   ù  s7   € ÷ =ñ =¤ð =¬s°T­zð =ÄeÈdÅlð =Ô^bÔcfÕ^gñ =r   c                óÀ   aa€ ^ RI Hp ^ RIHp \	        V 4      w  ooVV3R lpV'       d   \        V! V4      4      MRpTP                  Vf   \        MTVVRJ VR7      # )z°The stable gateway *name*'s service process supervises (in *profile*'s home when known): SCM
``running`` proves only the wrapper started, not that the gateway it hosts came up.rÔ  r‚  c           
      ó$  <€  \        SP                  4       ;'       g    ^ 4      p. pT  F   p\        SP                  \        4      ;_uu_ 4        T'       dk   TSP                  \        T4      4      P                  4        Uu0 uF  p\        TP                  4      kK  	  up9   d   TP                  \        T4      4       RRR4       K¢  	  T#   SP                  \        \        \
        3 d    . u # i ; iu upi   + '       g   i     Kå  ; i)r  N)
r9   r5   ÚErrorrL   r§   Ú	TypeErrorr   rn   ro   rª   )rP   r  Úownedr5   rA  rr   r‹  s   &    €€r   Úunder_serviceÚ-_service_gateway_ready.<locals>.under_service   sÓ   ø€ ð	Ü˜gŸk™k›m×0Ð0¨qÓ1ˆKð ˆÛˆCô ˜&Ÿ,™,¬×0Õ0ß ;ÀvÇ~Á~ÔVYÐZ]ÓV^ÓG_×GgÑGgÔGiÓ2jÑGiÀ!´3°q·u±u¶:ÑGiÑ2jÔ#jØ—L‘L¤ S£Ô*÷ 1Ñ0ñ ð ˆøð —‘œg¤z´9Ð=ô 	ØŠIð	üò 3k÷ 1×0Ð0ús4   ƒC ŸC Á4C>ÂC9Â!!C>Ã#C6Ã5C6Ã9C>Ã>DN)r»  r6   r"  Ú
pid_filter)rÞ  rÕ  r}  rƒ  r€  r
   rˆ  Ú_SERVICE_READY_TIMEOUT_S)	rš   r6  r»  rÕ  rƒ  rÁ  r6   rr   r‹  s	   &&&    @@r   Ú_service_gateway_readyrÅ  ù  sb   ù€ õ +Ý3Ü" 4Ó(�O€FˆGö÷ .5Œ4‘ Ó(Ô)¸$€DØ×2Ñ2Ø.7Ò.?Õ*ÀYÐUYØ˜T�\¨mð 3ó =ð =r   c                ó0   € V ^8„  d   QhR\         R\        /# )r   rš   r&   rG  )r   s   "r   r   r     s   € ÷ ñ œ3ð ¤4ñ r   c                 ó¾   €  ^ RI p \        T 4      ^,          P                  4       R8H  #   \         d     R# i ; i  TP                  \
        \        3 d     R# i ; i)r  NFr¦  )rr   ÚImportErrorr€  rŠ  r¾  rL   ÚAttributeErrorr  s   & r   Ú_service_runningrÊ    s_   € ðÛðÜ˜DÓ! !Õ$×+Ñ+Ó-°Ñ:Ð:øô ô Úðûð �L‰Lœ'¤>Ð2ô Úðús   ‚* ‡"< ª9¸9¼AÁAc                ó(   € V ^8„  d   QhR\         RR/# r<  r+   )r   s   "r   r   r     s   € ÷ /`ñ /`¤Dð /`¨Tñ /`r   c                ó4  € ^ RI Hp \        V P                  R4      ;'       g    . 4      pV P	                  R\        V4      4       \        V P                  R4      ;'       g    . 4      pV P                  R4      ;'       g    / P                  4        UUu/ uF  w  rEWB9   g   K  WEbK  	  ppp\        V P                  R4      4      p. p. p	\        \        V4       EFç  p
VP                  V
4      ;'       g    / p V'       d¦   \        P                  ! 4       \        VP                  R4      ;'       g    ^ 4      8  dj   \        V
4      '       dY   V	P                  V
4       \        RV
 R	\        \        VR,          4      \        P                  ! 4       ,
          4       R
24       KÍ  V! V
4       \!        Y P                  R4      ;'       g    / P                  V
4      V'       d   \"        MR4      '       gŽ   \        VP                  R4      ;'       g    ^ 4      ^,           pRVR\        P                  ! 4       \%        \&        ^\%        V^,
          ^4      ,          ,          \(        4      ,           /Wj&   \+        RV
 R24      hVP-                  V
R4       VP                  V
4       W£9  d   VP                  V
4       EKç  EKê  	  W0R&   W�R&   V'       d   W`R&   MV P-                  RR4       V	'       d"   \+        RRP5                  V	4      ,           4      hV'       d$   \        RRP5                  V4      ,           4       R# R# u uppi   \.         dB   p\0        P3                  RY­4       \        RT
 24       T	P                  T
4        Rp?EK¶  Rp?ii ; i)a’  Restart the SCM services recorded on *token*; one leaves the token only once the gateway it
supervises is ready. Failed ones stay on the token so a retry sees them.

A recovering launch (``token["recovery"]``) probes readiness briefly, and a running service
whose gateway was not ready is not re-probed before its backoff (``service_retry``) elapses:
the debt stays owed without stalling every command.rÉ  rû  rü  rý  Úservice_retryÚrecoveryÚnext_atu     âš  Windows gateway service z.: its gateway was not ready; next check after rÅ  rþ  NÚattemptsr¥  z0 is running but its gateway did not become readyz=Could not restart Windows gateway service %s after update: %su1     âš  Could not restart Windows gateway service: z.Could not restart Windows gateway service(s): r  u-   
  âœ“ Restarted Windows gateway service(s): )r¡   rÆ  rR   r0   Ú
setdefaultrQ  r:   r’  r   r™  ÚtimerS   rÊ  rª   r  r9   rÅ  Ú_SERVICE_READY_PROBE_SÚminÚ_SERVICE_RETRY_BASE_SÚ_SERVICE_RETRY_MAX_Sr"   r‹  r   r   Úwarningr|   )rÕ   rÆ  rû  Úverified_restartsrš   ÚstateÚretryÚ
recoveringrý  Úfailed_servicesÚservice_nameÚbackoffrÐ  r   s   &             r   Ú_resume_windows_servicesrß    s  € õ EÜ�E—I‘I˜jÓ)×/Ð/¨RÓ0€HØ	×ÑÐ(¬$¨x«.Ô9Ü˜UŸY™YÐ';Ó<×BÐBÀÓCÐØ-2¯Y©Y°Ó-G×-MÐ-MÈ2×,TÑ,TÔ,VÔkÑ,V™[˜TÐZ^ÑZjŒ[ˆTŠ[Ñ,V€EÑkÜ�e—i‘i 
Ó+Ó,€JØÐØ€OÜœC ×*ˆØ—)‘)˜LÓ)×/Ð/¨Rˆð	1ßœeŸjšj›l¬U°7·;±;¸yÓ3I×3NÐ3NÈQÓ-OÔOÔTdÐeq×TrÒTrØ×&Ñ& |Ô4ÜÐ6°|°nð E*Ü*-¬e°G¸IÕ4FÓ.GÌ%Ï*Ê*Ë,Õ.VÓ*WÐ)XÐXYð[ô \áÙ*¨<Ô8Ü)¨,¿¹ÐCUÓ9V×9\Ð9\ÐZ\×8aÑ8aÐbnÓ8oßDNÕ*@ÐTX÷Zò Zä˜wŸ{™{¨:Ó6×;Ð;¸!Ó<¸qÕ@�Ø'1°8¸YÌÏ
Ê
ËÔWZÜ)¨A´°XÀµ\À1Ó1EÕ,EÕEÔG[óX]õ I]ð '^�Ñ#ä"Ð%5°l°^ÐCsÐ#tÓuÐuØ�I‰I�l DÔ)Ø×%Ñ% lÔ3ØÔ4Ø!×(Ñ(¨×6ò 5ñ# +ð. #4Ð
ÑØ'ˆ*ÑßØ!&ˆoÒà�	‰	�/ 4Ô(ßÜÐKÈdÏiÉiÐXgÓNhÕhÓiÐißÜÐ>ÀÇÁÐK]ÓA^Õ^Ö_ñ ùóG løô. ô 	1Ü�N‰NÐZÐ\hÔnÜÐEÀlÀ^ÐTÔUØ×"Ñ" <×0Ó0ûð	1úsP   Â
MÂ%MÃ<MÄ0MÄ5A2MÆ)$MÇMÇ'MÇ9MÈB*MÍNÍ5NÎNc                ó^   € V ^8„  d   QhR\         R\        R\        \         \        3,          /# ©r   r×  rÙ  r&   )r,   rR   r’   )r   s   "r   r   r   Q  s*   € ÷ 'ñ '¬ð '¼ð 'ÄÄtÌTÀzÕARñ 'r   c                ó"  aa	€ \        R4      ;_uu_ 4        ^ RIHoHo	 RRR4       / p\	        V P                  4       4       F8  w  r4\        W43V	3R llRV4      '       g   K!  \        V4      V\        V4      &   K:  	  . pV Fu  pVP                  R4      VP                  R4      rGV'       g   K.  V'       g   K8  \        WGVP                  R4      3V3R	 llR
V4      '       g   Kd  VP                  V4       Kw  	  W%3#   + '       g   i     Lç; i)a  Spawn the restart watcher for each paused profile gateway and unmapped argv; ``(launched
profiles, launched unmapped entries)``. Nothing leaves the token here: a watcher only proves a
relaunch was scheduled, so every entry stays owed until ITS gateway is verified ready.z-Could not load Windows gateway restart helper)Ú*launch_detached_gateway_restart_by_cmdlineÚ'launch_detached_profile_gateway_restartNc                 ó:   <€ S! \        V 4      \        V4      4      # rb   )r   r9   )rA  Úorä  s   &&€r   r¹  Ú+_relaunch_paused_gateways.<locals>.<lambda>[  s   ø€ Ñ2YÔZ]Ð^_ÓZ`ÔbeÐfgÓbhÔ2ir   z=Could not restart Windows gateway profile %s after update: %sr  r5   r6   c                 ó>   <€ S! \        V 4      \        V4      VR 7      # )r|  )r9   rR   )ræ  rV  rB  rã  s   &&&€r   r¹  rç  b  s   ø€ ñ  ZDÜ�A“œ˜Q› aõZ)r   zDCould not restart unmapped Windows gateway (pid %s) after update: %s)r#   r  rã  rä  r#  rQ  r   r9   r   r0   rª   )
r×  rÙ  Úlaunchedr6  Úold_pidÚlaunched_unmappedr+  r  rã  rä  s
   &&      @@r   Ú_relaunch_paused_gatewaysrì  Q  sæ   ù€ ô 
ÐH×	IÕ	Ißz÷ 
Jð €HÜ" 8§>¡>Ó#3Ö4ÑˆÜ˜gÖiØTÐV]÷_ô _ä%(¨£\ˆH”S˜“\Ó"ñ 5ð ÐÛˆØŸ	™	 &Ó)¨5¯9©9°UÓ+;ˆgç‰4—G‘G¤	°7ÀeÇiÁiÐPVÓFWö +)à*pÐry÷!{ô !{ð ×$Ñ$ UÖ+ñ ð Ð&Ð&÷# 
J×	Iús   –	C>Ã>D	c                óR   € V ^8„  d   QhR\         R\        R\        \        ,          /# rá  )r,   rR   r9   )r   s   "r   r   r   l  s*   € ÷ 	Nñ 	N¤Tð 	N´Tð 	NÌ$ÌsÍ)ñ 	Nr   c                óˆ  € V P                  4        Uu. uF  p\        V4      NK  	  ppYA Uu. uFF  qUP                  R4      '       g   K  VP                  R4      '       g   K4  \        VR,          4      NKH  	  up,          p\        V Uu0 uF  q3^ 8”  g   K  V! V4      '       g   K  VkK  	  up4      # u upi u upi u upi )ag  Old PIDs a restart watcher is still waiting on, sorted; empty when every relaunch can have run.

``_spawn_gateway_restart_watcher`` respawns the gateway only once the PID it was handed is gone,
so while any of them is alive the relaunch has provably not started yet. Pure function of data
(``pid_exists`` is injected) so the decision is testable off Windows.
r  r5   )rP  r9   r0   r#  )r×  rÙ  Ú
pid_existsr5   Ú
candidatesr+  s   &&&   r   Ú_pending_relaunch_pidsrñ  l  s˜   € ð '/§o¡oÔ&7Ó8Ñ&7˜s”#�c–(Ñ&7€JÐ8Ø°(Óe±(¨¿i¹iÈ×>OÔ$ÐTY×T]ÑT]Ð^c×TdÔ$”3�u˜U•|Ö$±(ÑeÕe€JÜ¡*ÓL¡*˜3°a±”3¹JÀs¿O—3�3¡*ÑLÓMÐMùò 9ùÚeùÚLs(   “B5­B:Á
B:Á#B:ÂB?ÂB?Â(B?c                ó<   € V ^8„  d   QhR\         R\        R\        /# rá  )r,   rR   rS   )r   s   "r   r   r   x  s&   € ÷ Qñ Q¬ð Q¼ð QÌeñ Qr   c                ój   € ^ RI Hp \        WV4      '       g   \        # \	        V4      \        ,           # )u„  Liveness budget for the post-relaunch poll.

The base window assumes the watchers respawn immediately. When an old PID is still alive the
watcher is still in its wait loop, so the poll must reach at least the watcher's own deadline â€”
otherwise ``hermes update`` declares "no stable gateway process appeared" for a gateway that was
never scheduled to appear inside the window (#107002).
)Ú!GATEWAY_RESTART_WATCHER_TIMEOUT_S)r  rô  rñ  Ú_RELAUNCH_VERIFY_TIMEOUT_SrS   )r×  rÙ  rï  rô  s   &&& r   Ú_relaunch_verify_timeout_srö  x  s-   € õ EÜ! (°j×AÒAÜ)Ð)ÜÐ2Ó3Ô6PÕPÐPr   c                ó0   € V ^8„  d   QhR\         R\        /# )r   r+  Útakenrv  )r   s   "r   r   r   †  s   € ÷ Xñ X¤$ð X¬sñ Xr   c                ón  a aaaaaaaaa	a
aa€ ^ RI o
^ RIHoHoHo ^ RIHo \        S P                  R4      ;'       g    . 4      R,          \        S P                  R4      ;'       g    ^ 4      uooS P                  R4      S P                  R4      uoo	R	 VV VVVV	3R
 lloR VVV
VVV3R lloV3R l# )a{  ``pid_filter`` matching the gateway an unmapped entry's replay started: a gateway running the
same arguments after the (normalized) interpreter on the entry's home, born after the process it
replaces, not one another entry already vouched for. Two homes can run identical selectorless argv,
so argv alone would let home B's gateway retire home A's debt (a service gateway on another home
included; on A's home only one gateway can run). Only an entry recorded before ``home`` was
captured (no key: a pre-durable-pause updater's token) keeps the argv-only match; a recorded
``home`` that is empty proves no runtime and is never matched.N)Ú_looks_like_gateway_processÚ_same_hermes_homere  r>  r  ºé   NNr5   r6   rF  c                ó0   € V ^8„  d   QhR\         R\        /# rY   rZ   )r   s   "r   r   Ú,_unmapped_ready_filter.<locals>.__annotate__”  s   € ÷ ~ñ ~œ#ð ~¤$ñ ~r   c                 ó¼   <€ R S9  d   R# S'       g   R# S! V 4      S! V 4      r!VRJ;'       d/    S! VS4      ;'       d    SRJ ;'       g    VRJ ;'       g    VS8„  # )r6   TFNrc   )	r5   Ú	live_homerF  rû  r+  r?  re  r6   Úold_cts	   &  €€€€€€r   Úsame_runtimeÚ,_unmapped_ready_filter.<locals>.same_runtime”  sn   ø€ Ø˜ÔÙßÙÙ(¨Ó-Ñ/EÀcÓ/J�2Ø Ð$×}Ð}Ñ):¸9ÀdÓ)K×}Ð}ÐQWÐ[_ÐQ_×Q|ÐQ|ÐceÐimÐcm×Q|ÐQ|ÐqsÐv|Ñq|Ð}r   c                ó0   € V ^8„  d   QhR\         R\        /# rY   rZ   )r   s   "r   r   rÿ  œ  s   € ÷ ñ ”Sð œTñ r   c                 ó$  <€ V S8X  g   V S9   d   R #  \        SP                  V 4      P                  4       ;'       g    . 4      R,          S8H  ;'       d    S! V 4      ;'       d	    S! V 4      #   SP                  \        \
        3 d     R # i ; i)Frü  )rR   rn   r}   r¾  rL   r§   )r5   rú  Úoldrr   r  Útailrø  s   &€€€€€€r   r®   Ú'_unmapped_ready_filter.<locals>.matchesœ  s‹   ø€ Ø�#Œ:˜ œÙð	Ü˜Ÿ™¨Ó,×4Ñ4Ó6×<Ð<¸"Ó=¸bÕAÀTÑI÷ *ð *ÑNiÐjmÓNn÷ *ð *Ù$ SÓ)ð+øà—‘œg¤zÐ2ô 	Úð	ús"   “*A/ ¾A/ ÁA/ Á&A/ Á/BÂBc                 óv   <€ \        V 4       Uu. uF  pS! \        V4      4      '       g   K  VNK   	  up# u upi rb   )r  r9   )rP   r5   r®   s   & €r   r¹  Ú(_unmapped_ready_filter.<locals>.<lambda>¤  s-   ø€ Ô(;¸DÔ(AÓWÑ(A ÁWÌSÐQTËX×EVŸ˜Ñ(AÒWùÒWs   �6­6)
rr   rF   rú  rû  re  rO  r?  rR   r0   r9   )r+  rø  rú  rû  r?  re  r6   r®   r  r  rr   r  r  s   ff@@@@@@@@@@@r   Ú_unmapped_ready_filterr  †  s‰   ÿü€ ó ßeÑeÝ>Ü�U—Y‘Y˜vÓ&×,Ð,¨"Ó-¨bÕ1´3°u·y±yÀÓ7G×7LÐ7LÈ1Ó3M€I€Dˆ#Ø—9‘9˜VÓ$ e§i¡i°£o€L€Dˆ&÷~õ ~÷õ ô XÐWr   gš™™™™™Ù?g       @c          
      ób   € V ^8„  d   QhR\         R\        R\        R\        R,          R\        /# )r   Útargetsr�  rø  Úrespawn_windowNr&   )rR   rS   rT   r,   )r   s   "r   r   r   «  s>   € ÷ G+ñ G+œtð G+¬uð G+¼Sð G+ÔRWÐZ^ÕR^ð G+Ôjnñ G+r   c                óf  aa€ ^ RI Ho / p/ p\        4       p\        4       p\        4       pT^T;'       g    R,          ,           \        ,           \        ,           p	 \
        P                  ! 4       p
W©8¼  d   V# V  Uu. uF:  q»^ ,          V9  g   K  V^ ,          V9  g   K"  W¡8  g   V^ ,          V9   g   K8  VNK<  	  ppV'       gb   V  UUUu. uF(  w  rÞpWÔ9  g   K  WÖ9  g   K  WØ9  g   K  W×9  g   K&  VNK*  	  ppppVe$   V'       d   VP                  V4       W£,           pKË  V# . oR VV3R llpVP                  4        VP                  R VP                  4        4       4       V F¬  w  ppp \        V! V4      4      pT'       g   TP                  TR4       K5  T'       d   TMTR,          pTP                  T4       Te*   YØ9  d$   TP                  T4       \!        YT,           4      pY¥P#                  YÚ4      ,
          \        8¼  g   K¨  TYM&   K®  	  \%        V4      \%        V4      ,           \%        V 4      8  g   EKí  \
        P&                  ! \        4       EK
  u upi u upppi   \         d5   p\        P                  RTT4       TP                  T4        Rp?EK?  Rp?ii ; i)	uÑ  ``{key: pids}`` for each ``(key, probe, claim_all)`` target whose gateway stayed visible for
a whole confirmation window. All targets share one loop, so N targets cost one window, not N:
one fleet process scan per tick (``probe(scan)`` calls ``scan()`` only if it needs the fleet),
and each target is credited only on its own hits. *taken* holds, while a target is probed, the
PIDs earlier targets vouched for (all of a profile's, the first of an unmapped entry's) so one
gateway never retires two debts. A hit provisional at the deadline still finishes its window;
a probe that raises leaves its target unready.

*respawn_window*: a target's own liveness budget, in two parts. The restart watcher only spawns
once the paused PID is gone, and that wait is charged to the *old* process â€” 25â€“35 s of a shared
30 s deadline on a busy update â€” while a cold gateway then needs >11 s before its control socket
answers. So (a) a target first seen late gets ``respawn_window`` counted from its sighting, and
(b) a target the deadline expires on without ever being seen gets ONE extra window, because the
spawn it is waiting for may not have happened yet. Charging that wait to the new process is what
made an update report "relaunch was not verified alive" for a gateway that was up seconds later;
the verdict is committed and never revisited, so the stale debt surfaced as a manual follow-up on
the next launch. Both parts are bounded, so a relaunch that truly never happens still fails
closed. ``None`` keeps the single shared budget. Each target earns its sighting extension once,
and the whole poll stops at the entry deadline plus both windows and one confirmation tick: a
replacement that flaps in and out must not renew its budget forever.
r‘  rg   Nc                ó$   € V ^8„  d   QhR\         /# r*   ©rR   )r   s   "r   r   Ú'_poll_until_ready.<locals>.__annotate__×  s   € ÷ 	ñ 	”dñ 	r   c                  óh   <€ S'       g"   SP                  \        S ! R R7      4      4       S^ ,          # )Tr!  )rª   rR   )r  Úfleets   €€r   ÚscanÚ_poll_until_ready.<locals>.scan×  s&   ø€ ßØ—‘œTÑ"3ÀÔ"FÓGÔHØ˜•8ˆOr   c              3   ó4   "  € T F  q F  q"x € K  	  K  	  R # 5irb   rc   )rä   rP   r5   s   &  r   rå   Ú$_poll_until_ready.<locals>.<genexpr>Ü  s   é € ÐD¡^˜Tºt¸”S¹t‘S£^ùs   ‚z4Could not verify Windows gateway %s after update: %s:Nrý  N)r  r  rT   Ú_READY_CONFIRM_SÚ_READY_INTERVAL_Sr™  rš  rÅ   ÚclearrP  rR   r   r   r×  rq   r‹  ri   rÑ  rî   r›  )r  r�  rø  r  ÚreadyÚsincerC  ÚgracedÚ
first_seenÚ	hard_stoprJ   rï   r?  ÚkeyÚ_probeÚ_allÚstarvedr  rb  Ú	claim_allrP   r   Úvouchedr  r  s   &&&&                   @@r   Ú_poll_until_readyr(  «  sL  ù€ õ, 5Ø€EØ€EÜ“%€FÜ“%€FÜ“e€JØ˜1 × 5Ð 5°#Õ6Õ6Ô9IÕIÔL]Õ]€IØ
Ü�oŠoÓˆØÔØˆLÙ%Óx™g˜¨1­°UÑ):”1¸qÀ½tÈ6Ñ?Q”1ÐWZÔWeÐijÐklÕimÐqvÑiv—1�1™gˆÐxßÙ4;õ r±GÑ0˜s¨DØÑ*ô Ø/2Ñ/@ô ØEHÑEZô Ø_bÑ_p÷ �s±GˆGò ràÒ)¯gØ—‘˜gÔ&ØÕ/�ÙØˆLØˆ÷	ñ 	ð 	�‰ŒØ�‰ÑD U§\¡\¤^ÓDÔDÛ%,Ñ!ˆC�˜	ðÜ™E $›KÓ(�÷
 Ø—	‘	˜#˜tÔ$Ùß'‘d¨T°"­XˆGØ�L‰L˜Ô!ØÒ)¨cÔ.Cð —‘˜sÔ#Ü˜x¨~Õ)=Ó>�Ø×%Ñ% cÓ/Õ/Ô3CÖCØ$�“
ñ' &-ô( ˆu‹:œ˜F›Õ#¤c¨'£l×2Ü�KŠKÔ)×*ùòM yùôrøô$ ô Ü—‘ÐUÐWZÐ\_Ô`Ø—
‘
˜3”ÞûðúsN   Á=I%ÂI%Â!I%Â7I%ÃI*ÃI*Ã%I*Ã-I*Ã5I*Å4I1É1J0É<(J+Ê+J0c                ó@   € V ^8„  d   QhR\         R\         R\        RR/# )r   rÕ   r×  rÙ  r&   Nrø  )r   s   "r   r   r   õ  s/   € ÷ )rñ )r¬Tð )r¼Tð )rÌTð )rÐVZñ )rr   c           
     ó  a€ \        R4      ;_uu_ 4        ^ RIHp ^ RIHo ^ RIHp RRR4       \        P                  ! 4       \        WX4      ,           p\        4       p\        VP                  4       4       UUu. uF,  w  rxRV3\        X! V4      4      \        V4      3V3R llR3NK.  	  p	ppT	\        V4       U
Uu. uF  w  r«R	V
3\!        W¶4      3R
 lR3NK  	  upp
,          p	\#        W•V\$        R7      p\        V4       Uu. uF  pRV3V9   g   K  VNK  	  pp\        V4       U
Uu. uF  w  r«R	V
3V9   g   K  VNK  	  pp
pVP'                  4        UUu. uF  qÿ F  pVNK  	  K  	  pppWÐR&   V P)                  R4      ;'       g    / P                  4        UUu/ uF  w  ppVV9  g   K  VVbK  	  uppV R&   V P)                  R	4      ;'       g    .  Uu. uF  pVV9  g   K  VNK  	  upV R	&   V'       dE   \+        \,        4      ;_uu_ 4        SP/                  \        \        V4      4      R4       RRR4       V'       d   \1        RRP3                  V4       24       V'       d   \1        R\5        V4       R24       \        \        V4      \        V4      ,
          4      V Uu. uF   pVV9  g   K  RVP)                  R4       2NK"  	  up,           pV'       dJ   \1        RRP3                  V4      ,           R,           4       \7        RRP3                  V4      ,           4      hR#   + '       g   i     EL; iu uppi u upp
i u upi u upp
i u uppi u uppi u upi   + '       g   i     EL;; iu upi )aÏ  Retire each relaunched runtime on ITS OWN readiness: a profile on a stable gateway in its
profile home, an unmapped entry on a stable gateway running its argv. A watcher only proves a
relaunch was scheduled, and another target's readiness proves nothing about this one.

A parent Job Object denying CREATE_BREAKAWAY_FROM_JOB can kill the gateway on updater teardown.
Vouched PIDs are persisted so a death AFTER updater exit is reported by the next CLI invocation.z/Could not load Windows gateway liveness helpersrV   rÔ  r‚  Nr6  c                 ó4   <a€ SP                  VV3R  lR7      # )c                 óV   <€ V  Uu. uF  p\        V4      S8w  g   K  VNK  	  up# u upi rb   )r9   )ÚpsrA  ræ  s   & €r   r¹  ÚE_verify_relaunched_gateways_alive.<locals>.<lambda>.<locals>.<lambda>  s#   ø€ ±"Ó&D±"¨Q¼¸A»À!¹§q q±"Ò&DùÒ&Ds   †&�&)r6   rÃ  )r†  )Ú_scanrB  ræ  rÕ  s   &&f€r   r¹  Ú3_verify_relaunched_gateways_alive.<locals>.<lambda>  s(   ù€ Ð`o÷  aCñ  aCØÔDð aCô aFr   TrÙ  c                 ó   € V! V ! 4       4      # rb   rc   )r  Úfs   &&r   r¹  r0    s   € ÑWXÑY]ÓY_ÔW`r   F)r  Úrelaunched_profilesr×  zpost-update relaunchu.   
  âœ“ Restarting Windows gateway profile(s): r  u     âœ“ Restarting z% unmapped Windows gateway process(es)úpid r5   u:   
  âš  Windows gateway restart could not be verified for: z’
    (The respawned gateway may have been killed by a parent Job Object during updater teardown, #48820.)
    Recover with: hermes gateway restartz>Windows gateway relaunch after update was not verified alive: )r#   rF   rW   rÞ  rÕ  r}  rƒ  r™  rš  rö  rT   r#  rQ  r
   r9   rí   r  r(  rõ  rP  r0   r   r   rŠ  r  r|   rî   r"   )rÕ   r×  rÙ  rW   rƒ  r�  rø  rš   rê  r  rÔ   r+  r  Úready_profilesÚready_unmappedrP   r5   rŒ  r2  rk  ÚunreadyrÕ  s   &&&                  @r   Ú!_verify_relaunched_gateways_aliver8  õ  s:  ø€ ô 
ÐJ×	KÕ	KÝ.Ý.Ý7÷ 
Lô �ŠÓ Ô#=¸hÐR]Ó#^Õ^€HÜ“€Eô ciÐiq×iwÑiwÓiyÔbzô|ÙbzÑQ^ÐQUð ˜DÐ!´4¹ÈÓ8MÓ3NÔRUÐV]ÓR^ö $FØGKóMÙbzð ñ |àÜ )¨(Ô 3ô5Ù 3‘H�Að ˜a�Ô1GÈÓ1UÓ"`ÐbgÓhÙ 3ò5õ 5€Gä˜g°ÔGaÔb€EÜ'-¨hÔ'7ÓVÑ'7˜t¸IÀtÐ;LÐPUÑ;U—d�dÑ'7€NÐVÜ,5°hÔ,?Ô\Ñ,?¡ ÀJÐPQÀ?ÐV[ÑC[—e�eÑ,?€NÑ\Ø"'§,¡,¤.ÔA¡.˜$ºD°S“#¹D‘#¡.€JÑAð $2Ð
Ñ Ø/4¯y©y¸Ó/D×/JÐ/JÈ×.QÑ.QÔ.SÔoÑ.S¡F A sÐWXÐ`nÑWnœ˜˜CšÑ.SÒo€Eˆ*ÑØ%*§Y¡Y¨zÓ%:×%@Ð%@¸bÐ%@Ó]Ñ%@˜qÀQÈnÑE\Ÿ˜Ñ%@Ñ]€Eˆ*ÑßÜ”i× Õ Ø×4Ñ4´V¼CÀ
»OÓ5LÐNdÔe÷ !çÜÐ?ÀÇ	Á	È.Ó@YÐ?ZÐ[Ô\ßÜÐ!¤# nÓ"5Ð!6Ð6[Ð\Ô]Ü”S˜“]¤S¨Ó%8Õ8Ó9Ñ\dó  =AÑ\dÐWXÐhiÐqÑhÔ=R¸tÀAÇEÁEÈ%ÃLÀ>Ó=RÑ\dñ  =Aõ  A€GßÜØIÈDÏIÉIÐV]ÓL^Õ^ð b7õ 7ô	
ô
 Ð[Ð^b×^gÑ^gÐhoÓ^pÕpÓqÐqñ ÷9 
L×	KÐ	Küó|ùó5ùò WùÛ\ùÛAùó pùÚ]ç × Ð üò =Ase   •L2Á<2MÃ MÄMÄMÄ.MÅ MÅMÆ"M#Æ3M#Ç	M)Ç,M)È%M.Ê0	NÊ>NÌ2M	Í.M?	c                ó6   € V ^8„  d   QhR\         R,          RR/# r�  r+   )r   s   "r   r   r   !  s   € ÷ #ñ #´¸µð #Àñ #r   c                óÊ  € ^ RI Hp V '       d   V P                  R4      '       g   R# ^ RIpVP	                  \
        4       V! 4       P                  4       '       g   V P                  R4      R8w  d   RV R&   R# V P                  R4      '       d   \        \        P                  4      M	\        4       ;_uu_ 4        \        V 4       RRR4       R#   + '       g   i     R# ; i)z>Restart Windows profile gateways previously paused for update.r”   rÖ  NÚplatformrÍ   FrÎ  )r¡   r•   r0   ÚatexitÚ
unregisterr  r¢   r   Úsysrl  r   Ú_resume_unless_torn)rÕ   r•   r<  s   &  r   r  r  !  s™   € å(ß˜Ÿ	™	 /×2Ò2Ùó Ø
×ÑÔ;Ô<Ù‹4×Ñ×Ò %§)¡)¨JÓ"7¸7Ô"BØ!&ˆˆoÑÙð ).¯	©	°*×(=Ò(=ŒœŸ™Ô	$Ä;Ã=×	PÑ	PÜ˜EÔ"÷ 
Q×	P×	PÒ	Pús   Â;CÃC"	c                ó(   € V ^8„  d   QhR\         RR/# r<  r+   )r   s   "r   r   r   7  s   € ÷ !ñ !œtð !¨ñ !r   c                ó2  € ^ RI Hp V P                  R4      '       dG   VP                  V 4      w  r#V'       g,   \	        RV R24       RV R&   W0R&   VP                  V 4       R#  \        V 4       VP                  V 4       R#   TP                  T 4       i ; i)	zGResume the paused set, or leave it owed when the checkout is not whole.r<  Úpause_idu&     âš  Paused gateway(s) left stopped: zC.
    The next `hermes` command (or `hermes update`) restarts them.FrÖ  Úresume_deferredN)rÞ  r=  r0   Útree_is_wholer  ÚsyncÚ_resume_paused_set)rÕ   rK  ÚwholeÚwhys   &   r   r?  r?  7  s–   € å>Ø‡y�y�×ÒØ!×/Ñ/°Ó6‰
ˆßô Ð:¸3¸%ð @Vð Vô Wà%*ˆE�/Ñ"Ø'*Ð#Ñ$Ø×Ñ˜eÔ$Ùð!Ü˜5Ô!à×Ñ˜%Ö øˆ×Ñ˜%Õ ús   Á%B ÂBc                ó(   € V ^8„  d   QhR\         RR/# r<  r+   )r   s   "r   r   r   L  s   € ÷ +#ñ +#œdð +# tñ +#r   c                ó   a aa	a
a€ ^ RI Ho S P                  R4      R8X  d   ^ RIHp V! S 4      # S! 4       P                  4        . o	R V	3R llpV! V 3R l4       \        S P                  R4      ;'       g    / 4      p\        S P                  R	4      ;'       g    . 4      pV'       g;   \        ;QJ d    R
 V 4       F  '       g   K   RM	  RM! R
 V 4       4      '       d¸   \        W44      w  o
oS
'       g	   S'       d   V! V
VV 3R l4       M. S R&   \        \        V4      \        S
4      ,
          4      V Uu. uF  qUS9  g   K  RVP                  R4       2NK!  	  up,           pV'       d(   S	P                  RRP                  V4      ,           4       M)S P                  R4      '       d   R VV 3R llpV! V4       V! V 3R l4       S	'       d   \        RP                  S	4      4      hRS R&   R# u upi )z­Bring every paused runtime back; each one is retired from *token* only on its own verified
start, and one failure (an SCM service, a profile) never keeps the others stopped.r”   r;  rÍ   )Úresume_paused_setc                ó   € V ^8„  d   QhRR/# rÑ  rc   )r   s   "r   r   Ú(_resume_paused_set.<locals>.__annotate__X  s   € ÷ &ñ &˜ñ &r   c                 ó~   <€  V ! 4        R #   \          d&   pSP                  \        T4      4        R p?R # R p?ii ; irb   )r   rª   r   )Ústepr   Úfailuress   & €r   ÚattemptÚ#_resume_paused_set.<locals>.attemptX  s0   ø€ ð	&ÙŽFøÜô 	&Ø�O‰OœC ›H×%Ò%ûð	&ús   ƒ Œ<—7·<c                  ó   <€ \        S 4      # rb   )rß  r  s   €r   r¹  Ú$_resume_paused_set.<locals>.<lambda>^  s   ø€ Ô,¨UÔ3r   r×  rÙ  c              3   óB   "  € T F  qP                  R 4      x € K  	  R# 5irh  ri  rj  s   & r   rå   Ú%_resume_paused_set.<locals>.<genexpr>a  s   é € Ð7©h¨—u‘u˜V—}�}«hùs   ‚TFc                  ó   <€ \        SS S4      # rb   )r8  )ré  rë  rÕ   s   €€€r   r¹  rT  d  s   ø€ Ô=¸eÀXÐO`Ôar   r3  r4  r5   z0Could not restart every paused Windows gateway: r  rÚ  c                ó   € V ^8„  d   QhRR/# rÑ  rc   )r   s   "r   r   rM  m  s   € ÷ 	5ñ 	5˜Dñ 	5r   c                  ó`   <€ S ! 4       P                  S4      '       g   \        R 4      hRSR&   R# )z+Windows gateway cold-start was not verifiedFrÚ  N)r“  r"   )r•   rÕ   s   €€r   Ú
cold_startÚ&_resume_paused_set.<locals>.cold_startm  s-   ø€ Ù“4×@Ñ@À×GÒGÜ"Ð#PÓQÐQØ/4ˆEÐ+Ó,r   c                  ó   <€ \        S 4      # rb   )r�  r  s   €r   r¹  rT  t  s   ø€ Ô1°%Ô8r   r  rÖ  N)r¡   r•   r0   Ú!hermes_cli.update_cmd_posix_pauserK  rž  r,   rR   rz  rì  r#  rT   rª   r|   r"   )rÕ   rK  rQ  r×  rÙ  rk  Únot_launchedrZ  r•   rP  ré  rë  s   f       @@@@r   rF  rF  L  sž  ü€ õ )Ø‡y�y�Ó Ô'ÝGÙ  Ó'Ð'ñ ƒD×+Ñ+Ô-Ø€H÷&ð &ñ Ô3Ô4Ü�E—I‘I˜jÓ)×/Ð/¨RÓ0€HÜ�E—I‘I˜jÓ)×/Ð/¨RÓ0€Hß—3“3Ñ7©hÓ7—3—3’3Ñ7©hÓ7×7Ò7Ü&?ÀÓ&SÑ#ˆÐ#ß×(ÙÖaÕbà+-ˆEÐ'Ñ(Üœc (›m¬c°(«mÕ;Ó<Ù+3ó@SÙ+3 aÐ@QÑ7QÔ!ˆd�1—5‘5˜“<�.Ó!©8ñ@Sõ SˆçØ�O‰OÐNÐQU×QZÑQZÐ[gÓQhÕhÔiøØ	�‰Ð,×	-Ò	-÷	5ñ 	5ñ 	�
Ôñ Ô8Ô9ßÜ˜4Ÿ9™9 XÓ.Ó/Ð/Ø"€Eˆ/Óùò!@Ss   Ä?G;ÅG;c                ó$   € V ^8„  d   QhR\         /# )r   r  r`   )r   s   "r   r   r   z  s   € ÷ "
ñ "
Ô_cñ "
r   c                óÒ  a	€ ^ RI Hp  V! 4       P                  V4       \        V\        4      '       g   R# R R lpTp\        R4      ;_uu_ 4        T! V P                  VP                  R4      ;'       g    . 4       RRR4       \        VP                  R	4      ;'       g    . 4      pVP                  R
4      ;'       g    / o	V! V P                  V4       V! V P                  R V	3R lV 4        4       4       T! V P                   V	3R lVP                  R4      ;'       g    .  4       4       \#        \        4      ;_uu_ 4        ^ RIHp T! V P                  V P                  V P(                  \+        V P,                  4      V P                   V P                  ;'       g    \/        V P                   4      RP1                  V P
                  4      ;'       g    RR7       RRR4       R#   \         dE   pRT n        T P
                  P                  \        T4      4       \        RT 24        Rp?ELRp?ii ; i  + '       g   i     ELË; i  + '       g   i     R# ; i)zÒResume gateways paused for a Windows update and fold the token into ``outcome``'s systemd/launchd-style
bookkeeping so reconciliation never reports a healthy gateway as unaccounted. Must never abort the update.r”   Tu2     âš  Windows gateway service restart incomplete: Nc                ó(   € V ^8„  d   QhR\         RR/# )r   Útargetr&   Nr  )r   s   "r   r   Ú@_resume_windows_gateways_and_merge_outcome.<locals>.__annotate__‰  s   € ÷ Sñ Sœtð S¨tñ Sr   c                 ód   a € S P                  V 3R  l\        P                  V4       4       4       R# )c              3   ó8   <"  € T F  qS9  g   K  Vx € K  	  R # 5irb   rc   )rä   Úitemrb  s   & €r   rå   ÚU_resume_windows_gateways_and_merge_outcome.<locals>._extend_unique.<locals>.<genexpr>Š  s   øé € ÐRÑ';˜tÈ6Ñ?Q—d’dÓ';ùs   ƒ�
N)Úextendr,   r  )rb  rQ  s   f&r   Ú_extend_uniqueÚB_resume_windows_gateways_and_merge_outcome.<locals>._extend_unique‰  s   ø€ Ø�‰ÔR¤t§}¡}°UÔ';ÓRÖRr   zRCould not merge Windows relaunch outcome into fleet reconciliation bookkeeping: %sr3  rý  rþ  c              3   ó8   "  € T F  q'       g   K  Vx € K  	  R # 5irb   rc   )rä   rA  s   & r   rå   Ú=_resume_windows_gateways_and_merge_outcome.<locals>.<genexpr>“  s   é € Ð0vÑ<p°qÓtu·²Ó<pùs   ‚	�
c              3   óF   <"  € T F  pSP                  V4      x € K  	  R # 5irb   ri  ©rä   r2  rþ  s   & €r   rå   rl  “  s$   øé € Ð<pÑ^oÐYZÐ=M×=QÑ=QÐRS×=TÐ=TÓ^oùs   ƒ!c              3   ól   <"  € T F)  p\        SP                  V4      ;'       g    T4      x € K+  	  R # 5irb   )r   r0   rn  s   & €r   rå   rl  ”  s1   øé € Ð2|Ñ_zÐYZ´3Ð7G×7KÑ7KÈAÓ7N×7SÐ7SÐRS×3TÐ3TÓ_zùs   ƒ!4¥4rû  )Úrecord_gateway_restartr  )rý  r3  Úexternally_supervised_profilesÚkilled_pidsÚfailed_unitsÚ
incompleteÚphase_error)r¡   r•   r  r   rt  Úphase_errorsrª   r   r  r(  r,   r   r3  r0   rR   rý  Úfailed_or_stale_unitsr   Úhermes_cli.update_receiptrp  rq  r#  rr  r:   r|   )
ÚoutcomeÚ_windows_gateway_resumer  r•   Ú_windows_resume_excri  rÕ   Úwindows_restartedrp  rþ  s
   &&&      @r   Ú*_resume_windows_gateways_and_merge_outcomer}  z  só  ø€ õ )ðZÙ
‹×2Ñ2Ð3JÔKô Ð-¬t×4Ò4ÙõSð $€Eä	Ðj×	kÕ	kÙ�w×2Ñ2°E·I±IÐ>SÓ4T×4ZÐ4ZÐXZÔ[÷ 
lä˜UŸY™YÐ';Ó<×BÐBÀÓCÐØ—y‘yÐ!3Ó4×:Ð:¸ÐÙ�7×-Ñ-Ð/@ÔAÙ�7×.Ñ.Ñ0vÔ<pÑ^oÔ<pÓ0vÔwÙ�7×0Ñ0Ô2|Ð_d×_hÑ_hÐisÓ_t×_zÐ_zÐxzÐ_zÓ2|Ô}Ü	”)×	Õ	ÝDÙØ&×9Ñ9Èw×OjÑOjØ+2×+QÑ+QÔ_eÐfm×fyÑfyÓ_zØ ×6Ñ6À7×CUÑCU×C|ÐC|ÔY]Ð^e×^{Ñ^{ÓY|ØŸ	™	 '×"6Ñ"6Ó7×?Ð?¸4õ		
÷ 
Ñ	øô+ ô Zð "ˆÔØ×Ñ×#Ñ#¤CÐ(;Ó$<Ô=ÜÐBÐCVÐBWÐX×YÒYûðZú÷ 
l×	kÐ	kú÷ 
×	Ð	ús6   ‰G/ Á-IÅ
BIÇIÇ/H>Ç:9H9È9H>ÉI	ÉI&	c                óN   € V ^8„  d   Qh/ ^ \         9   d   \        R,          ;R&   # )r   NrÀ   )Ú__conditional_annotations__rº   )r   s   "r   r   r      s%   € ÷ ñ ÷j 3Ò 2œ9 tÕ+Ñ 2òkr   )ÚserveÚ	dashboard>   ú-crØ   r½   ú-rú-sú-tú-zú--inú--modelr¾   ú--resumeú--skillsú	--oneshotr¿   ú
--continueú
--providerú
--toolsetsú--reasoningú--usage-file)gš™™™™™É?rc   rb   )NN)r£  )jr  ró  ÚloggingÚ
contextlibr   r   r   r   rH   rª  ré   rp  r>  rÒ  r™  r   r   r   Úpathlibr
   Úhermes_cli.update_cmd_commonr   Ú	getLoggerr   r  r   r#   r(   r7   rN   rj   rw   rp   r‡   r‰   r�   rµ   r©   rº   rÆ   rÀ   rÉ   ró   rù   r  ÚVENV_HOLDERS_EXITr
  r  r  r,  r:  rD  rJ  rN  rW  r^  ra  rs  rI  r{  r€  rŽ  r•  rh   r¢  r­  r½  rÆ  rÏ  râ  r"   rä  r  r  r%  r0  r8  r]  rN  rT  rU  r�  r“  rž  r¹  rÄ  rÓ  rÕ  rÖ  rÅ  rÊ  rß  rì  rõ  rñ  rö  r  r  r  r(  r8  r  r?  rF  r}  r   )r  s   @r   Ú<module>r—     sˆ  øðöó ß MÓ MÛ 	Û 	Û Û Û 
Û ß ,Ñ ,Ý å 5à	×	Ò	Ð2Ó	3€à*Ð ð°t÷ ð ô8ó ð8õ=õõõ 5õ.õ,õ/òõeð1ÀT÷ 1õhñ  )ò *ó  Ð ð /3Ð Ó 2õ%õ6)õXõ4ð$ Ð õõ&õ(õ4õ$õ,õ27õ	õBõJõ$õ2Iõ6tõõ40õWõ	/÷õdõXð.vØFHðvð AEðvà:>ðvàQU÷vð,ZÀ$÷ ZðmÀD÷ mõô@3˜ô 3õ%EðPK bð K¸÷ KòSô"!.õHõ D?õNA÷ &õR0õ6+÷>8õvZ÷>+jð\  Ð ð Ð ØÐ ØÐ ÷=õ6õ/`õd'ð0 "Ð õ	NõQõXðB Ð ØÐ ÷G+õT)rõX#õ,!õ*+#÷\"
r   