+
    jHàjì  ã            
      óD  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	H
t
 ^ RIHt ]P                  ! ]4      tRt^tRt]! ]4      P)                  4       P*                  P*                  t]3R R	 lltR
 R ltR]P2                  /R R lltR]RRRRR]RR/R R lltR# )aŽ  Stop a gateway whose checkout was moved back to a release that predates the gateway runtime.

Downgrading is unsupported, but a manual ``git checkout <older release>`` under a running gateway
leaves this process serving every local session from code the tree no longer has. Older clients
cannot attach to it, and older ``hermes gateway run`` refuses because this process still holds the
profile. Nothing on the older side knows how to stop it. So the gateway watches its own tree, using the boot
revision ``gateway.code_skew`` records. Once the checkout has provably moved (two consecutive
reads, never while an update holds the tree) to code whose state-store modules lack the runtime
ledger, it logs why and stops with the normal drain (a hard exit if that stop fails on the older
tree). The stop is a plain stop, never a restart of this process, but it exits with the
service-restart code (75): systemd relaunches on any exit, while the launchd plist's
``KeepAlive.SuccessfulExit=false`` parks exit 0 and would leave the gateway down for good. Either
supervisor then starts the older release's own gateway from the tree on disk. Every uncertain read
keeps it up.
)ÚannotationsN)ÚPath)ÚCallableÚOptional)Ú!GATEWAY_SERVICE_RESTART_EXIT_CODEg      >@z-CREATE TABLE IF NOT EXISTS session_admissionsc               ó    € V ^8„  d   QhRRRR/# )é   Úrootr   ÚreturnÚbool© )Úformats   "ÚC/home/ubuntu/.hermes/hermes-agent/gateway/runtime_downgrade_exit.pyÚ__annotate__r   #   s   € ÷ Yñ Y ð Y¸ñ Yó    c                ó*  €  V P                  R4       Uu. uF  qP                  RRR7      NK  	  pp\        T4      ;'       d:    \        ;QJ d    R T 4       F  '       g   K   RM	  RM! R T 4       4      '       * # u upi   \         d     R# i ; i)z[True only when the checkout's state-store modules are readable and none defines the ledger.zhermes_state*.pyz	utf-8-sigÚreplace)ÚencodingÚerrorsFc              3  ó4   "  € T F  p\         V9   x € K  	  R # 5i)N)Ú_RUNTIME_SCHEMA_MARKER)Ú.0Útexts   & r   Ú	<genexpr>Ú(tree_predates_runtime.<locals>.<genexpr>)   s   é € Ð$XÑPWÈÔ%;¸tÖ%CÓPWùs   ‚T)ÚglobÚ	read_textÚOSErrorr   Úany)r	   ÚpathÚsourcess   &  r   Útree_predates_runtimer!   #   s€   € ðØVZ×V_ÑV_Ð`rÔVsÓtÑVsÈd—>‘>¨;¸y�>ÖIÑVsˆÐtô �‹=×XÐX§£Ñ$XÑPWÓ$X§§¢Ñ$XÑPWÓ$XÓ!XÔXÐXùò uøÜô Úðús!   ‚B •A>°B Á>B ÂBÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r   Úupdate_in_progressr   ÚpredateszCallable[[], bool]r
   úOptional[str]r   )r   s   "r   r   r   ,   s#   € ÷ ;ñ ;°$ð ;ÐBTð ;ÐYfñ ;r   c               ór   € V '       d   V'       g   V! 4       '       g   R# RP                   ! \        V 4      !  # )zJThe log line when this gateway must stop for a downgraded tree, else None.NzÇThis gateway loaded {}, but its checkout is now at {}, a release that predates the gateway runtime. Downgrading is unsupported; stopping so the service manager starts the older release's own gateway.)r   Útuple)Úskewr#   r$   s   &$$r   Údowngrade_reasonr)   ,   s1   € ç×%©X¯ZªZÙð%ç%+¡Vð,ä-2°4«[ñ:ð ;r   Ú	hard_exitc               ó    € V ^8„  d   QhRRRR/# )r   r*   zCallable[[int], None]r
   ÚNoner   )r   s   "r   r   r   5   s   € ÷ ñ Ð.Cð ÐSWñ r   c             ƒ  ó¢   "  €  V P                  4       G Rj  x€L
  R#  L  \         d"    \        P                  R4       T! ^4        R# i ; i5i)a	  The normal drain, and a hard exit if it raises. The stop path lazily imports modules that
the older tree on disk no longer has; a stop that raised never sets the shutdown event and has
already disarmed its own watchdog, so without this the process idles on forever.Nz;Gateway stop failed on the downgraded checkout; exiting now)ÚstopÚ	ExceptionÚloggerÚ	exception)Úrunnerr*   s   &$r   Ú_stop_or_exitr3   5   s=   é € ðØ�k‰k‹m×ÔøÜô Ü×ÑÐVÔWÙ�!�ðüs1   ‚A„  —˜  œAž   (AÁAÁAÁAÚpoll_sÚskew_fnÚupdate_prober$   Ú	max_pollsc               ó$   € V ^8„  d   QhRRRRRR/# )r   r4   Úfloatr7   zOptional[int]r
   r,   r   )r   s   "r   r   r   @   s#   € ÷ ($ñ ($°uð ($ØO\ð($Øhlñ($r   c             ƒ  ó&  aa
a"  € Vf   ^ RI Hp Vf   ^ RIHp Vo
VoR V
VV3R llp^ ;rx\	        V RR4      '       dÍ   Ve   W…8  dÁ   V^,          p\
        P                  ! V4      G Rj  x€L
 p	V	'       d
   V^,           M^ pV\        8¼  d\   \        P                  RV	4       W�n
        \        V n        \
        P                  ! 4       P                  \        V 4      4      V n        R# \
        P"                  ! V4      G Rj  x€L
  KÝ  R# R#  L¡ L5i)	zíSupervised gateway watcher: ``runner.stop()`` after ``_CONFIRMATIONS`` consecutive downgrade reads.

The probes are bound here, at gateway start: a lazy import after the tree moved would load the
older release's module into this process.N)Údetect_code_skew)r#   c               ó   € V ^8„  d   QhRR/# )r   r
   r%   r   )r   s   "r   r   Ú/runtime_downgrade_watcher.<locals>.__annotate__M   s   € ÷ \ñ \�=ñ \r   c                 ó`   <€  S! 4       p \        S! 4       V SR7      #   \          d    R p  L"i ; i)T)r#   r$   )r/   r)   )ÚbusyÚobserve_skewÚobserve_updater$   s    €€€r   Ú_readÚ(runtime_downgrade_watcher.<locals>._readM   s:   ø€ ð	Ù!Ó#ˆDô  ¡£À4ÐRZÔ[Ð[øô ô 	ØŠDð	ús   ƒ �-¬-Ú_runningFz%s)Úgateway.code_skewr;   Úhermes_cli.update_lockr#   ÚgetattrÚasyncioÚ	to_threadÚ_CONFIRMATIONSr0   ÚerrorÚ_exit_reasonr   Ú
_exit_codeÚget_running_loopÚcreate_taskr3   Ú_runtime_downgrade_stopÚsleep)r2   r4   r5   r6   r$   r7   rB   ÚseenÚpollsÚreasonr@   rA   s   &$$$d$    @@r   Úruntime_downgrade_watcherrU   @   sî   úé € ð ‚ÝAØÒÝMØ$€LØ)5€N÷\ò \ð Ð€DÜ
�&˜* e×
,Ò
,°)Ò2CÀuÔGXØ��
ˆÜ×(Ò(¨Ó/×/ˆß!ˆt�aŽx qˆØ”>Ô!Ü�L‰L˜˜vÔ&Ø"(Ôô !BˆFÔô .5×-EÒ-EÓ-G×-SÑ-SÔTaÐbhÓTiÓ-jˆFÔ*ÙÜ�mŠm˜FÓ#×#Ò#ñ' HYÑ
,á/ñ" 	$ùs+   …A&DÁ+DÁ,DÁ8B
DÄDÄDÄD)Ú__doc__Ú
__future__r   rH   ÚloggingÚosÚpathlibr   Útypingr   r   Úgateway.restartr   Ú	getLoggerÚ__name__r0   ÚPOLL_SrJ   r   Ú__file__ÚresolveÚparentÚ_PROJECT_ROOTr!   r)   Ú_exitr3   rU   r   r   r   Ú<module>re      s¯   ðñõ  #ã Û Û 	Ý ß %å =à	×	Ò	˜8Ó	$€à	€Ø€ØHÐ Ù�X“×&Ñ&Ó(×/Ñ/×6Ñ6€ð (5÷ Yõ;ðÀbÇhÁh÷ ð($¸vð ($Ètð ($Ðbfð ($Ø-Bð($Ø_c÷($ñ ($r   