+
    jHàjíG  ã            	       ó  € R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHtHt ^ RI	H
t
 ^Kt^NtR R ltRtRt]! ]
R,          R	,          4      t]! ]
R
,          R,          4      tRt]! ]
R,          R,          4      t]! ]
R,          R,          4      tRtRtRt^<tRtRt]P8                  ! R]P:                  4      tR R ltRIR R llt RIR]PB                  /R R lllt"RIRRRRR]PF                  R]PB                  /R R lllt$R ]/R! R" llt%R# R$ lt&R% R& lt'0 RJmt(R' R( lt)RIR) R* llt*RIR+ R, llt+R- R. lt,RKR0 R1 llt-R2R3/R4 R5 llt.R6 R7 lt/R8 R9 lt0R: R; lt1R< R= lt2R>R/R ]/R? R@ llt3]3R ]RA]RB]/RC RD lllt4RERF/RG RH llt5R# )LzBShared gateway restart constants and supervisor detection helpers.N)ÚCallableÚMapping)ÚDEFAULT_CONFIGc                ó0   € V ^8„  d   QhR\         R\         /# )é   Ú
returncodeÚreturn)Úint)Úformats   "Ú4/home/ubuntu/.hermes/hermes-agent/gateway/restart.pyÚ__annotate__r      s   € ÷ ñ ´#ð ¼#ñ ó    c                ó    € V \         8X  d   ^ # V # )uâ  Translate gateway EX_CONFIG so launchd can park the job.

systemd uses ``RestartPreventExitStatus=78``; s6 maps 78â†’125. launchd cannot
gate on a specific status, and unconditional ``KeepAlive=true`` respawns 78
forever (#89477). The generated plist uses ``KeepAlive.SuccessfulExit=false``;
mapping 78â†’0 is a deliberate stop. Exit 75 (please restart) and other
failures pass through so KeepAlive still relaunches them. Negative ``wait()``
codes (signals) are left to the caller.
)ÚGATEWAY_FATAL_CONFIG_EXIT_CODE)r   s   &r   Ú!map_fatal_config_exit_for_launchdr      s   € ð Ô3Ô3ÙØÐr   Ú"HERMES_GATEWAY_EXTERNAL_SUPERVISORÚHERMES_LAUNCHD_LABELÚagentÚrestart_drain_timeoutÚgatewayÚsignal_interrupt_grace_timeoutg      @Úrestart_after_turn_timeoutÚcron_drain_timeoutg      $@g      >@g      N@g       @z ^\s*exit timeout\s*=\s*(\d+)\s*$c                ó>   € V ^8„  d   QhR\         R\        R,          /# )r   Úprint_outputr   N©ÚobjectÚfloat)r
   s   "r   r   r   T   s   € ÷ !ñ !¬Vð !¼À½ñ !r   c                ó’   € \         P                  \        T ;'       g    R4      4      pVf   R# \        VP	                  ^4      4      # )z=Extract ``exit timeout = N`` from ``launchctl print`` output.Ú N)Ú_LAUNCHD_EXIT_TIMEOUT_REÚsearchÚstrr   Úgroup)r   Úmatchs   & r   Úparse_launchd_exit_timeoutr%   T   s:   € ä$×+Ñ+¬C°×0BÐ0BÀÓ,CÓD€EØ‚}ÙÜ�—‘˜Q“Ó Ð r   c                ón   € V ^8„  d   QhR\         \        \        3,          R,          R\        R,          /# ©r   ÚenvironNr   ©r   r"   )r
   s   "r   r   r   \   s,   € ÷ ñ œw¤s¬C xÕ0°4Õ7ð Ä3ÈÅ:ñ r   c                óì   € V f   \         P                  MT pR\        3 FQ  p\        VP	                  VR4      ;'       g    R4      P                  4       pVP                  R4      '       g   KO  Vu # 	  R# )ul  The ``ai.hermes.*`` launchd job label in *environ*, or ``None`` (no darwin gate).

launchd stamps ``XPC_SERVICE_NAME`` only on the job process it spawns. The generated plist
runs the stderr-timestamp wrapper there, so the gateway grandchild reads ``XPC_SERVICE_NAME=0``
and finds its label only in the wrapper's re-export, ``HERMES_LAUNCHD_LABEL``. Both go through
the same ``ai.hermes`` predicate: app-coalition labels (``application.<bundle>â€¦``, exported
into IDE integrated terminals) are not our job. ONE seam for every reader of launchd identity
(drain cap, restart route, control-socket supervisor declaration).
NÚXPC_SERVICE_NAMEr   z	ai.hermes)Úosr(   ÚLAUNCHD_LABEL_ENVr"   ÚgetÚstripÚ
startswith)r(   ÚenvÚvarÚlabels   &   r   Úlaunchd_job_labelr4   \   sd   € ð  šŒ"�*Š*¨W€CØ"Ô$5Ó6ˆÜ�C—G‘G˜C Ó$×*Ð*¨Ó+×1Ñ1Ó3ˆØ×Ñ˜K×(Ô(ØŠLñ 7ñ r   Úplatformc                óz   € V ^8„  d   QhR\         \        \        3,          R,          R\        R\        R,          /# )r   r(   Nr5   r   r)   )r
   s   "r   r   r   n   s7   € ÷ 
&ñ 
&¤7¬3´¨8Õ#4°tÕ#;ð 
&ÔQTð 
&ÔhkÐnrÕhrñ 
&r   c               ó*   € VR8w  d   R# \        V 4      # )ut  Return this process's ``ai.hermes.*`` launchd job label, or ``None`` off darwin.

``launchctl print`` reports ``exit timeout = 1`` for app-coalition labels â€” treating those as
a budget would cap the drain to 0 for a gateway Ctrl+C'd in an IDE terminal, hence the
predicate in :func:`launchd_job_label`. ``platform`` is data so the mapping logic is testable
on any host.
ÚdarwinN)r4   )r(   r5   s   &$r   Úlaunchd_service_labelr9   n   s   € ð �8ÔÙÜ˜WÓ%Ð%r   r(   ÚuidÚrunc                óþ   € V ^8„  d   QhR\         R,          R\        \         \         3,          R,          R\        R,          R\        R\        P
                  \         ,          3,          R\         R\        R,          /# )	r   r3   Nr(   r:   r;   .r5   r   )r"   r   r	   r   Ú
subprocessÚCompletedProcessr   )r
   s   "r   r   r   {   su   € ÷ %3ñ %3Ü��:ð%3ô ”Sœ#�XÕ Õ%ð%3ô 
ˆt�ð	%3ô
 
�#”z×2Ñ2´3Õ7Ð7Õ	8ð%3ô ð%3ô ˆT…\ñ%3r   c          	     ón  € T ;'       g    \        WR7      p V '       g   R# Vf   \        \        RR4      pVf   R# V! 4       pV^ 8X  d   RMRV 2p V! RRV RV  2.R	R	R
R^R7      pTP                  ^ 8w  d   R# \        TP                  4      #   \        \        P
                  \        3 d     R# i ; i)u¥  Live ``ExitTimeOut`` (seconds) launchd enforces for this gateway's job.

Returns ``None`` â€” meaning "no launchd budget applies" â€” when the process
is not launchd-owned (non-darwin, or no ``ai.hermes`` job label â€” see :func:`launchd_job_label`), ``launchctl`` is missing
or fails, or the print output carries no ``exit timeout`` line. Callers
must treat ``None`` as fail-open: the configured drain stands unchanged.
)r5   NÚgetuidÚsystemzgui/Ú	launchctlÚprintÚ/Tzutf-8Úreplace)Úcapture_outputÚtextÚencodingÚerrorsÚtimeout)
r9   Úgetattrr,   ÚOSErrorr=   ÚSubprocessErrorÚ
ValueErrorr   r%   Ústdout)r3   r(   r:   r;   r5   r@   ÚdomainÚprocs   &$$$$   r   Úread_launchd_exit_timeout_srR   {   sÆ   € ð ×FÐFÔ*¨7ÔF€EßÙØ
‚{Üœ˜X tÓ,ˆØŠ>ÙÙ‹hˆØ œ‰X¨¨c¨U |€Fð
ÙØ˜' f X¨Q¨u¨gÐ#6Ð7ØØØØØô
ˆð ‡�˜!ÔÙÜ% d§k¡kÓ2Ð2øô	 ”Z×/Ñ/´Ð<ô Úðús   ÁB Â B4Â3B4Úcleanup_reserve_sc                óV   € V ^8„  d   QhR\         R\         R,          R\         R\         /# )r   Údrain_timeoutÚlaunchd_exit_timeout_sNrS   r   ©r   )r
   s   "r   r   r   £   s:   € ÷ Fñ FÜðFä! D�LðFô ð	Fô
 ñFr   c          	     óŒ   € \        V 4      p\        V4      pVR8:  d   V# \        V\        V\        V4      ,
          R4      4      # )u>  Clamp a SIGTERM-driven stop drain to what launchd will actually allow.

``launchd_exit_timeout_s`` is the live ``exit timeout`` for this job (see
:func:`read_launchd_exit_timeout_s`); ``None`` means no launchd budget
applies and the configured drain is returned untouched. Otherwise the
drain may use at most ``exit_timeout - cleanup_reserve_s`` so the
post-drain teardown (interrupt agents, disconnect adapters, checkpoint
and close SQLite) still completes before launchd escalates to SIGKILL.
Never *extends* the drain â€” an operator who configured a short one
keeps it.
ç        )Ú_secondsÚminÚmax)rU   rV   rS   ÚdrainÚbudgets   &&$  r   Úresolve_launchd_capped_drainr_   £   sD   € ô$ �]Ó#€EÜÐ,Ó-€FØ�„}ØˆÜˆu”c˜&¤8Ð,=Ó#>Õ>ÀÓDÓEÐEr   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úrunnerr   r   )r
   s   "r   r   r   ¼   s   € ÷ añ a¬ð a´Eñ ar   c                ó|   € \        V R\        4      p\        V RR4      '       g   V# \        V\        V RR4      4      # )uÁ  Drain budget for the stop in progress on ``runner``.

Signal-driven stops under launchd are timed by launchd's live
``ExitTimeOut`` (``runner._launchd_exit_timeout_s``, set at boot);
everything else â€” in-band SIGUSR1 restart after the turn, ``--replace``
takeover, tests â€” keeps the configured drain. Duck-typed and
getattr-guarded on purpose: shutdown-path tests drive ``_stop_impl``
from bare doubles that are not ``GatewayRunner`` instances.
Ú_restart_drain_timeoutÚ_stop_requested_by_signalFÚ_launchd_exit_timeout_sN)rK   Ú%DEFAULT_GATEWAY_RESTART_DRAIN_TIMEOUTr_   )ra   r]   s   & r   Úeffective_stop_drain_timeoutrg   ¼   sA   € ô �FÐ4Ô6[Ó\€EÜ�6Ð6¸×>Ò>ØˆÜ'¨¬w°vÐ?XÐZ^Ó/_Ó`Ð`r   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   ra   Úwatchdog_delayr   r   )r
   s   "r   r   r   Ì   s!   € ÷ ñ ¬&ð Ä%ð ÌEñ r   c                ó|   € \        V4      p\        V RR4      '       g   V# \        V\        V RR4      \        R7      # )u#  Thread-watchdog leash for the stop in progress on ``runner``.

``watchdog_delay`` is the supervisor-agnostic leash (effective drain +
grace). Under launchd a signal-driven stop is SIGKILLed at the live
``ExitTimeOut`` â€” with a 60s budget the default leash (50 + 60 = 110s)
can never fire, so the forensic stack dump and ``os._exit`` the watchdog
exists for are lost. Clamp the leash to ``ExitTimeOut -
LAUNCHD_WATCHDOG_DUMP_MARGIN_S`` so the dump lands before SIGKILL. Same
duck-typing / fail-open rules as :func:`effective_stop_drain_timeout`.
rd   Fre   N)rS   )rZ   rK   r_   ÚLAUNCHD_WATCHDOG_DUMP_MARGIN_S)ra   ri   Úleashs   && r   Úeffective_stop_watchdog_delayrm   Ì   sB   € ô �^Ó$€EÜ�6Ð6¸×>Ò>ØˆÜ'ØŒw�vÐ8¸$Ó?ÔSqôð r   c                ó>   € V ^8„  d   QhR\         R,          R\        /# )r   Ú
error_codeNr   )r"   Úbool)r
   s   "r   r   r   â   s"   € ÷ Nñ N¬3°­:ð N¼$ñ Nr   c                ó´   € T ;'       g    RP                  4       P                  4       p\        V4      ;'       d    VR8H  ;'       g    VP                  R4      # )aÌ  True when an adapter's fatal error is a single-writer ownership conflict.

Adapters emit ``{scope}_lock`` with ``retryable=True`` so a *mid-run* reconnect can
recover; at startup a live foreign holder is a configuration conflict (two gateways
cannot poll one token), not a transient blip.  Matches by error CODE only, never text.

``BasePlatformAdapter._acquire_platform_lock`` emits ``{scope}_lock`` with ``retryable=True`` on
purpose: a *mid-run* reconnect must be able to recover once the live holder exits or a stale record is
cleared (#54167). This matches by error CODE only (the ``{scope}_lock`` / ``lock_conflict`` families
every adapter emits for scoped-lock and identity conflicts), never by message text.
r   Úlock_conflictÚ_lock)r/   Úlowerrp   Úendswith)ro   Úcodes   & r   Úis_global_startup_conflictrw   â   sK   € ð ×Ð˜"×#Ñ#Ó%×+Ñ+Ó-€DÜ�‹:×MÐM˜4 ?Ñ2×LÐL°d·m±mÀGÓ6LÐMr   c                ó`   € V ^8„  d   QhR\         \        \        3,          R,          R\        /# r'   ©r   r"   rp   )r
   s   "r   r   r   ò   s,   € ÷ añ a¬7´3¼°8Õ+<¸tÕ+Cð aÌtñ ar   c                ó   € V f   \         P                  MT pVP                  RR4      p\        VP                  R4      ;'       g†    VP                  R4      ;'       gm    T;'       d    VR8g  ;'       gV    \	        V4      ;'       gC    \        VP                  \        R4      4      P                  4       P                  4       \        9   4      # )ag  Return whether this gateway process is owned by a supervisor that RESTARTS it.

Selects the exit-75 restart route, so only markers of a manager with a restart policy count:
systemd ``INVOCATION_ID``, launchd ``XPC_SERVICE_NAME`` (or the wrapper-forwarded
``HERMES_LAUNCHD_LABEL`` the grandchild sees), the s6 sentinel, or the explicit
``--external-supervisor`` opt-in. The generalized ``HERMES_SUPERVISED_CHILD`` launcher marker is
deliberately NOT read here: the Windows Scheduled-Task launcher sets it without a restart policy
(#113670), and routing its ``/restart`` through exit 75 would leave the gateway dead.
r+   r   ÚINVOCATION_IDÚHERMES_S6_SUPERVISED_CHILDÚ0)
r,   r(   r.   rp   r4   r"   ÚEXTERNAL_GATEWAY_SUPERVISOR_ENVr/   rt   Ú_TRUTHY)r(   r1   Úxpc_services   &  r   Úis_gateway_supervisor_processr�   ò   sÀ   € ð  šŒ"�*Š*¨W€CØ—'‘'Ð,¨bÓ1€KÜ�—‘˜Ó(÷ `ð `¨C¯G©GÐ4PÓ,Q÷ `ð `ÐVa×VxÐVxÐfqÐuxÑfx÷ `ð `Ü$ SÓ)÷`ð `ä�s—w‘wÔ>ÀÓCÓD×JÑJÓL×RÑRÓTÔX_Ñ_óað ar   c                ó`   € V ^8„  d   QhR\         \        \        3,          R,          R\        /# r'   ry   )r
   s   "r   r   r     s(   € ÷ 2ñ 2¬'´#´s°(Õ*;¸dÕ*Bð 2Ìdñ 2r   c                óv   € V f   \         P                  MT pVP                  R4      '       d   R# \        V 4      # )u;  Return whether this gateway was launched by a generated service/launcher rather than a shell.

Superset of :func:`is_gateway_supervisor_process` that also honours ``HERMES_SUPERVISED_CHILD``,
the marker every generated launcher exports (systemd unit, launchd plist, s6 run script, Windows
Scheduled Task â€” see ``hermes_cli.main._apply_profile_override``). This is the identity the
self-targeting guards key on: a kill or lifecycle command issued from inside such a gateway takes
down the process hosting the caller with nobody at a terminal to bring it back (#113667).
ÚHERMES_SUPERVISED_CHILDT)r,   r(   r.   r�   )r(   r1   s   & r   Úis_supervised_gateway_launchr…     s1   € ð  šŒ"�*Š*¨W€CØ
‡w�wÐ(×)Ò)ÙÜ(¨Ó1Ð1r   c                ó$   € V ^8„  d   QhR\         /# )r   r   )rp   )r
   s   "r   r   r     s   € ÷ Qñ Q¤dñ Qr   c                 óŽ   € \         P                  P                  R4      ;'       g     \         P                  P                  R4      # )z­In a container (Docker/Podman) the detached setsid restart path dies with the cgroup,
so exit-75 service restart is the only viable path.  Own function so tests can mock it.z/.dockerenvz/run/.containerenv)r,   ÚpathÚexists© r   r   Úis_container_restart_contextr‹     s-   € ô �7‰7�>‰>˜-Ó(×PÐP¬B¯G©G¯N©NÐ;OÓ,PÐPr   rY   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   ÚvalueÚfallbackr   r   )r
   s   "r   r   r     s!   € ÷ ñ ”Fð ¤eð ´eñ r   c                ó`   €  \        \        V 4      R4      #   \        \        3 d    Tu # i ; i)z9Non-negative float, or ``fallback`` on non-numeric input.rY   )r\   r   Ú	TypeErrorrN   )r�   rŽ   s   &&r   rZ   rZ     s1   € ðÜ”5˜“< Ó%Ð%øÜ”zÐ"ô ØŠðús   ‚ —-¬-ÚfiniteFc                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r   ÚrawÚdefaultr‘   r   )r   r   rp   )r
   s   "r   r   r      s/   € ÷ 	Oñ 	O¤Vð 	O´eð 	OÌð 	OÔY^ñ 	Or   c               ó  € V e-   \        V \        4      '       d   V P                  4       '       g   V#  \        V 4      pT'       d   \        P                  ! T4      '       g   T# \        RT4      #   \        \
        3 d    Tu # i ; i)z“Parse a timeout where ``0`` is a deliberate disable (must NOT fall through
to ``default``), unlike None / blank / non-numeric (/ non-finite) input.rY   )	Ú
isinstancer"   r/   r   r�   rN   ÚmathÚisfiniter\   )r“   r”   r‘   r�   s   &&$ r   Ú_parse_timeout_keeping_zeror™      sp   € ð ‚{”z #¤s×+Ò+°C·I±I·K²KØˆðÜ�c“
ˆ÷ ¤T§]¢]°5×%9Ò%9ˆ7ÐN¼sÀ3È»ÐNøô ”zÐ"ô ØŠðús   ´A1 Á1BÂBc                ó0   € V ^8„  d   QhR\         R\        /# ©r   r“   r   r   )r
   s   "r   r   r   ,  s   € ÷ [ñ [¤Vð [´ñ [r   c                ó6   € \        T ;'       g    R\        4      # )zWParse a configured drain timeout; falsy (incl. ``0``) falls back to the shared default.N)r™   rf   ©r“   s   &r   Úparse_restart_drain_timeoutrž   ,  s   € ä& s§{ {¨dÔ4YÓZÐZr   c                ó0   € V ^8„  d   QhR\         R\        /# r›   r   )r
   s   "r   r   r   1  s   € ÷ Xñ X¬&ð X´Uñ Xr   c                ó"   € \        V \        4      # )zSParse the after-turn wait cap for in-band restart (``0`` = legacy immediate drain).)r™   Ú*DEFAULT_GATEWAY_RESTART_AFTER_TURN_TIMEOUTr�   s   &r   Ú parse_restart_after_turn_timeoutr¢   1  s   € ä& sÔ,VÓWÐWr   c                ó0   € V ^8„  d   QhR\         R\        /# r›   r   )r
   s   "r   r   r   6  s   € ÷ Pñ P¤&ð P¬Uñ Pr   c                ó"   € \        V \        4      # )u8  Parse the cron/api_server drain floor (``0`` = opt out; both interrupted on the chat budget).

``0`` is a deliberate opt-out â€” cron and api_server (/v1) work is then interrupted on the same budget as chat work, the
pre-#82161 behaviour â€” and must not fall through to the default, unlike empty/missing input.
)r™   Ú"DEFAULT_GATEWAY_CRON_DRAIN_TIMEOUTr�   s   &r   Úparse_cron_drain_timeoutr¦   6  s   € ô ' sÔ,NÓOÐOr   c                ó0   € V ^8„  d   QhR\         R\        /# r›   r   )r
   s   "r   r   r   ?  s   € ÷ iñ i¬fð i¼ñ ir   c                ó&   € \        V \        RR7      # )z9Parse the unexpected-signal post-interrupt grace timeout.T)r‘   )r™   Ú.DEFAULT_GATEWAY_SIGNAL_INTERRUPT_GRACE_TIMEOUTr�   s   &r   Ú$parse_signal_interrupt_grace_timeoutrª   ?  s   € ä& sÔ,ZÐcgÔhÐhr   Úelapsedc                ó`   € V ^8„  d   QhR\         R\         R\         R\         R\         R\         /# )r   rU   r   ri   r«   rS   r   rW   )r
   s   "r   r   r   D  s>   € ÷ +ñ +Üð+Ü.3ð+ÜHMð+ÜX]ð+äð+ô ñ+r   c               óÊ   € \        V 4      p\        V4      pVR8:  d   V# \        V4      \        V4      ,
          \        V\        4      ,
          p\        V\        Wg4      4      # )aU  Seconds the stop drain may wait on in-flight cron and api_server (/v1) work.

Clamped to what this process can honour: the watchdog hard-exits at ``watchdog_delay``,
so waiting past that leash minus ``cleanup_reserve_s`` swaps a cleanly-interrupted job
for a SIGKILL that leaves it wedged.  Never less than ``drain_timeout`` (only extends).
rY   )rZ   ÚCRON_DRAIN_CLEANUP_RESERVE_Sr\   r[   )rU   r   ri   r«   rS   r]   ÚfloorÚceilings   &&$$$   r   Úresolve_cron_drain_budgetr±   D  sY   € ô �]Ó#€EÜÐ'Ó(€EØ�„|ØˆÜ�~Ó&¬°'Ó):Õ:¼XÐFWÔYuÓ=vÕv€GÜˆu”c˜%Ó)Ó*Ð*r   Ú
headroom_sÚfloor_sc                ó`   € V ^8„  d   QhR\         R\         R\         R\         R\         R\        /# )r   rU   r   rS   r²   r³   r   )r   r	   )r
   s   "r   r   r   V  sH   € ÷ Wñ WÜðWÜ.3ðWäðWäINðWô ðWô 	ñ	Wr   c          	     óÒ   € \        V 4      p\        V4      pVR8”  d   V\        V4      ,           MRp\        \        \        V4      \        WW4      \        V4      ,           4      4      # )ae  Seconds systemd ``TimeoutStopSec`` must cover: the stop path may first wait
``cron_drain_timeout`` + ``cleanup_reserve_s`` for cron and api_server work, so sizing from the chat drain
alone lets systemd SIGKILL an in-budget drain.  A zero cron timeout is an opt-out.

``restart_drain_timeout`` is only the chat-turn interrupt budget (default 0). See #94759.
rY   )rZ   r	   r\   )rU   r   rS   r²   r³   r]   ÚcronÚcron_budgets   &&$$$   r   Ú resolve_systemd_timeout_stop_secr¸   V  sW   € ô �]Ó#€EÜÐ&Ó'€DØ:>À¼*�4œ(Ð#4Ó5Ö5È#€KÜŒs”8˜GÓ$¤c¨%Ó&=ÄÈÓ@TÕ&TÓUÓVÐVr   Úheadroomg      .@c          
      óT   € V ^8„  d   QhR\         R\         R\         R\         R\         /# )r   rU   Úafter_turn_timeoutr   r¹   r   rW   )r
   s   "r   r   r   g  s;   € ÷ Cñ CÜðCÜ.3ðCÜINðCÜ]bðCä
ñCr   c               óð   € \         ;QJ d    R W3 4       F  '       d   K   RM	  RM! R W3 4       4      '       g   \        P                  # \        V4      \	        W4      ,           \        V4      ,           # )ux  Seconds a CLI waits for the gateway PID to exit after SIGUSR1: the in-band after-turn
deferral, then the longest supervisor stop envelope â€” the one systemd's ``TimeoutStopSec`` is
sized from (cron drain + cleanup reserve, supervisor headroom, floor; #94759) â€” then
observer ``headroom``.

A non-finite drain means "wait indefinitely", not a crash in the integer envelope.
c              3   ó`   "  € T F$  p\         P                  ! \        V4      4      x € K&  	  R # 5i©N)r—   r˜   rZ   )Ú.0r�   s   & r   Ú	<genexpr>Ú3resolve_restart_exit_wait_budget.<locals>.<genexpr>q  s"   é € Ð_Ñ;^°%Œt�}Š}œX e›_×-Ð-Ó;^ùs   ‚,.FT)Úallr—   ÚinfrZ   r¸   )rU   r»   r   r¹   s   &&&$r   Ú resolve_restart_exit_wait_budgetrÄ   g  se   € ÷ ‹3Ñ_¸MÑ;^Ó_�3�3Š3Ñ_¸MÑ;^Ó_×_Ò_Ü�x‰xˆÜÐ&Ó'Ô*JÈ=Ó*mÕmÔpxð  zBó  qCõ  Cð  Cr   r¾   >   Ú1ÚonÚyesÚtrue)rY   )6Ú__doc__r—   r,   Úrer=   ÚsysÚcollections.abcr   r   Úhermes_cli.configr   Ú!GATEWAY_SERVICE_RESTART_EXIT_CODEr   r   r~   r-   r   rf   r©   Ú,DEFAULT_GATEWAY_POST_INTERRUPT_GRACE_TIMEOUTr¡   r¥   r®   ÚSYSTEMD_STOP_HEADROOM_SÚSYSTEMD_TIMEOUT_STOP_SEC_FLOORÚ LAUNCHD_GUI_EXIT_TIMEOUT_CLAMP_SÚLAUNCHD_STOP_CLEANUP_RESERVE_Srk   ÚcompileÚ	MULTILINEr    r%   r4   r5   r9   r;   rR   r_   rg   rm   r   rw   r�   r…   r‹   rZ   r™   rž   r¢   r¦   rª   r±   r¸   rÄ   rŠ   r   r   Ú<module>rÖ      s  ðÙ Hã Û 	Û 	Û Û 
ß -å ,ð %'Ð !ð "$Ð õð" #GÐ ð +Ð á(-¨n¸WÕ.EÐF]Õ.^Ó(_Ð %Ù16°~ÀiÕ7PÐQqÕ7rÓ1sÐ .Ø/2Ð ,ñ .3°>À'Õ3JÐKgÕ3hÓ-iÐ *ñ &+¨>¸'Õ+BÐCWÕ+XÓ%YÐ "ð  $Ð ð Ð Ø!%Ð ð $&Ð  Ø!%Ð ð "%Ð àŸ:š:Ð&IÈ2Ï<É<ÓXÐ õ!÷ñ$
&ÐWZ×WcÑWc÷ 
&ð 
&ñ%3ð )-ð%3ð ð	%3ð
 <F¿>¹>ð%3ð —L‘L÷%3ð %3ðPFð  >÷	Fõ2aõ ò& %€õN÷ a÷"2õQ÷ð	OÈu÷ 	Oõ[õ
Xõ
Põið
+Ø`cð+à;÷+ð& 7YñWà;ðWàQhðWð 4÷Wð Wð"CØei÷Cñ Cr   