+
    lHàjµ\  ã                  ó   a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
HtHt ^ RIHtHt ^ RIHtHtHt ^ RIHt ^ RIHtHt ^ RIHt ]P6                  ! ]4      tR	tR
tRSt ]!! 0 RTm4      t"R R lt#R R lt$ ! R R]%4      t&R t'R t(R t)R R lt*R R lt+R R lt,R R lt-].! 4       t/R]0R&   ].! 4       t1R]0R&    ! R R ]24      t3R! R" lt4R# R$ lt5R% R& lt6]R' R( l4       t7R) R* lt8].! 4       t9R]0R+&   R, R- lt:R. R/ lt;R0 R1 lt<R2 R3 lt=R4RR5RR6R7/R8 R9 llt>R5R/R: R; llt?R4RR5RR6R7/R< R= llt@R> R? ltAR@ tBRARBRCRBRDRB/RE RF lltCRG RH ltDRI RJ ltERUtFRKtGRL RM ltHRNR/RO RP lltIRNR/RQ RR lltJR# )Va1  Canonical Bot Chat transport and durable legacy delivery receipts.

Only gateway/session_bot.py admits execution. Old claimed/terminal records remain
inspectable; the legacy UI claim consumer is retired. No authority means refusal.
Receipt storage derives from FalconOrtiz's live-owner mailbox (#101564).
)ÚannotationsN)Ú	ExitStackÚcontextmanager)Úmake_user_dirÚunusable_dir_remedy)Úatomic_json_writeÚatomic_write_textÚfsync_directory)ÚPath)ÚAnyÚCallable)Ú	_FileLockÚbot_live_deliveryz	.sequencec               ó    € V ^8„  d   QhRRRR/# )é   Úhomer
   Úreturnú
str | None© )Úformats   "Ú</home/ubuntu/.hermes/hermes-agent/tools/bot_live_delivery.pyÚ__annotate__r       s   € ÷ ñ ˜ð  ñ ó    c                ó"  € ^ RI Hp V R,          P                  4       '       g   R# V! V R,          RR7      p VP                  R4      pV'       d   VP	                  VR,          4      MR VP                  4        #   TP                  4        i ; i)zRCurrent Bot Chat tip id, or None when the profile has no store or no Bot Chat yet.)Ú	SessionDBústate.dbNT)Údb_pathÚ	read_onlyzBot ChatÚid)Úhermes_stater   Úis_fileÚget_session_by_titleÚget_compression_tipÚclose)r   r   ÚdbÚrows   &   r   Ú_bot_chat_tipr&       sn   € å&à�:Õ×&Ñ&×(Ò(ÙÙ	˜4 *Õ,¸Ô	=€BðØ×%Ñ% jÓ1ˆß47ˆr×%Ñ% c¨$¥iÔ0¸TÐAà
�‰�
øˆ�‰�
ús   ¸A< ÁA< Á<Bc               ó    € V ^8„  d   QhRRRR/# )r   Úprofile_homeú
Path | strr   údict[str, Any] | Noner   )r   s   "r   r   r   .   s   € ÷ Tñ T¨Jð TÐ;Pñ Tr   c                ó~  € ^ RI Hp \        V 4      P                  4       pV! V^R7      pVP                  R8w  g   VP
                  f   \        R4      hVR,          P                  4       '       g   R# \        V4      p\        \        V4      T;'       g    RRVP
                  P                  T;'       g    RR	7      # )
aV  Discover the profile authority and its exact Bot Chat without acquiring a lease.

``session_id`` is the current Bot Chat tip, or ``''`` when the profile has none yet: the
authority's deliver door creates it on first delivery (main's ``--create-if-missing``),
so a missing chat is not a refusal. None only when the profile has no store at all.©Údiscover_gateway_endpoint©ÚtimeoutÚreadyNúprofile authority is not readyr   Ú T)r(   Ú
session_idÚ	canonicalÚlease_idÚlive_session_id)Úhermes_cli.gateway_runtimer-   r
   ÚresolveÚstateÚendpointÚ
ValueErrorr    r&   ÚdictÚstrÚinstance_id)r(   r-   r   Ú	discoveryÚtips   &    r   Úfind_canonical_live_ownerrA   .   s¢   € õ Eä�Ó×%Ñ%Ó'€DÙ)¨$¸Ô:€IØ‡�˜'Ô! Y×%7Ñ%7Ò%?ÜÐ9Ó:Ð:Ø�:Õ×&Ñ&×(Ò(ÙÜ
˜Ó
€CÜœS ›Y°3·9°9¸"ÈØ"×+Ñ+×7Ñ7ÈÏÈÐPRôTð Tr   c                  ó   € ] tR t^AtRtRtR# )ÚPreDialErroruT  The authority call died before its RPC reached the socket: nothing was admitted, so
this is a definite no-send the sender may safely retry â€” never the ambiguous
post-admission state that orders 'do not resend' (#139303). A ``ValueError`` like the
"authority is not ready" refusals it wraps, so existing ``except ValueError`` callers hold.r   N©Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   r   r   rC   rC   A   s   † õcr   rC   c                ó   € \        V RV4      # )zHCall only this home's already-running authority; never start a fallback.zbot_relay.deliver©Ú_authority_rpc©r   Úparamss   &&r   Úauthority_deliveryrP   H   s   € ä˜$Ð 3°VÓ<Ð<r   c                ó   € \        V RV4      # )z�The same authority's ``bot_relay.settle``: the delivery id settled as never sent, or its
existing receipt (``gateway/session_bot.py:_settle``).zbot_relay.settlerL   rN   s   &&r   Úauthority_settlerR   M   s   € ô ˜$Ð 2°FÓ;Ð;r   c                ó   a aaaaaa	a
aaa€ ^ RI o	^ RIHo ^ RIHoHoHoHo ^ RIH	o
 \        S 4      P                  4       o RoVVVV	V
VVV VVV3R lp  S	P                  4        ^ RIHp T! T! 4       4      #   \         d    S	P                  T! 4       4      u # i ; i  \"         d$   pS'       g   \%        \'        T4      4      Thh Rp?ii ; i)é    Nr,   )ÚGATEWAY_WS_PROTOCOLÚGatewayClientÚ_session_ticketÚgateway_ws_target)ÚconnectFc            
   “  óÒ  <"  € S
P                  SS^R7      G Rj  x€L
 p V P                  R8w  g   V P                  f   \        R4      hV P                  pS
P                  S	SV4      G Rj  x€L
 pS! W4      w  r4S! W4^
RR7      ;_uu_4       GRj  x€L
 pVP                  S8w  d   \        R4      hS! V4      ;_uu_4       GRj  x€L
 pRoVP
                  ! S3/ SB G Rj  x€L
 uuRRR4      GRj  x€L
  uuRRR4      GRj  x€L
  #  Lñ L¢ L~ LK L0 L! L  + GRj  x€L 
 '       g   i     M; iRRR4      GRj  x€L 
  R#   + GRj  x€L 
 '       g   i     R# ; i5i)é   r.   Nr0   r1   )ÚsubprotocolsÚopen_timeoutÚproxyzauthority protocol mismatchT)Ú	to_threadr9   r:   r;   ÚsubprotocolÚrpc)r?   r:   ÚticketÚurlÚ	protocolsÚwsÚclientrU   rV   rW   ÚasynciorY   r-   rX   r   ÚmethodrO   Úrpc_starteds          €€€€€€€€€€€r   ÚrequestÚ_authority_rpc.<locals>.request\   s*  øé € à!×+Ñ+Ð,EÀtÐUVÐ+ÓW×Wˆ	Ø�?‰?˜gÔ%¨×);Ñ);Ò)CÜÐ=Ó>Ð>Ø×%Ñ%ˆØ×(Ñ(¨¸$ÀÓI×IˆÙ*¨8Ó<‰ˆá˜3ÀRÈt×T×TÕTÐXZØ�~‰~Ð!4Ô4Ü Ð!>Ó?Ð?Ù$ R×(×(Ô(¨FØ"�Ø#ŸZšZ¨Ñ9°&Ñ9×9÷ )×(Ñ(÷ U×TÒTñ Xñ Jñ Uñ )á9ñ )ñ U÷ )×(×(Ð(ú÷ U×T×T×T×TÔTüsâ   ƒE'›DœAE'Á,DÁ-%E'ÂDÂE'Â1E
ÃDÃE
ÃD	Ã$DÃ%D	Ã(E
Ã5D
Ã6E
Ã:E'ÄDÄE'ÄE'ÄE'ÄE
ÄD	ÄE
ÄE'ÄD4Ä!D$Ä"
D4Ä-D4Ä/E
Ä7E'ÅEÅE'Å
E$	ÅEÅ
E$	ÅE$	Å	E')Ú
_run_async)rg   r7   r-   Úhermes_cli.gateway_clientrU   rV   rW   rX   Úwebsockets.asyncio.clientrY   r
   r8   Úget_running_loopÚRuntimeErrorÚrunÚmodel_toolsrl   Ú	ExceptionrC   r=   )r   rh   rO   rj   rl   ÚexcrU   rV   rW   rg   rY   r-   rX   ri   s   fff   @@@@@@@@r   rM   rM   S   s¦   ÿú€ ÛÝDßpÓpÝ1ä�‹:×ÑÓ€DØ€K÷:÷ :ð ð	*Ø×$Ñ$Ô&õ
 	+Ù™'›)Ó$Ð$øô ô 	*Ø—;‘;™w›yÓ)Ò)ð	*ûô ô ßÜœs 3›xÓ(¨cÐ1Øûðús6   ÁA8 Á%B Á8!BÂB ÂBÂB ÂCÂ*CÃCc               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r)   Úownerúdict[str, Any]r   zdict[str, str]r   )r   s   "r   r   r   {   s!   € ÷ ñ �ð  Nð °~ñ r   c                óŒ  € \          Uu/ uF  q"VP                  V4      bK  	  pp\        ;QJ d*    R  VP                  4        4       F  '       d   K   RM	  RM! R  VP                  4        4       4      '       g   \	        R4      hVR,          \        \        V 4      P                  4       4      8w  d   \	        R4      hV# u upi )c              3  ót   "  € T F.  w  r\        V\        4      ;'       d    T;'       g    VR9   x € K0  	  R# 5i)r3   N)r3   r6   )Ú
isinstancer=   )Ú.0ÚkeyÚvalues   &  r   Ú	<genexpr>Ú_owner.<locals>.<genexpr>~   s9   é € ð 1Ù!/‘:�3ô ˜%¤Ó%×]Ð]¨5×+\Ð+\°CÐ;\Ñ4\Ô]Û!/ùs   ‚8 	8ª8FTzEowner requires profile_home, session_id, lease_id and live_session_idr(   z)owner belongs to a different profile home)Ú_OWNER_KEYSÚgetÚallÚitemsr;   r=   r
   r8   )r   rv   r|   Úpinneds   &&  r   Ú_ownerr…   {   s�   € Ý-8Ó9©[ c�5—9‘9˜S“>Ò!©[€FÐ9ç‹3ñ 1Ø!'§¡¤ó1�3�3Š3ñ 1Ø!'§¡¤ó1÷ 1ò 1äÐ`ÓaÐaØˆnÕ¤¤T¨$£Z×%7Ñ%7Ó%9Ó!:Ô:ÜÐDÓEÐEØ€Mùò :s   ‰Cc               ó    € V ^8„  d   QhRRRR/# )r   r}   r=   r   r   )r   s   "r   r   r   †   s   € ÷ ñ ˜ð  ñ r   c                óz   € \        V \        4      '       d   \        P                  ! R V 4      f   \	        R4      hV # )z[0-9a-f]{32,64}z5delivery id must be 32 to 64 lowercase hex characters)rz   r=   ÚreÚ	fullmatchr;   )r}   s   &r   Ú_delivery_idrŠ   †   s1   € Ü�eœS×!Ò!¤R§\¢\Ð2DÀeÓ%LÒ%TÜÐPÓQÐQØ€Lr   c               ó    € V ^8„  d   QhRRRR/# )r   r   r)   r   r
   r   )r   s   "r   r   r   Œ   s   € ÷ @ñ @�
ð @˜tñ @r   c                óX   € \        V 4      P                  4       R ,          \        ,          # )Úruntime)r
   r8   ÚDELIVERY_DIR_NAME)r   s   &r   Ú_rootr�   Œ   s    € Ü�‹:×ÑÓ )Õ+Ô.?Õ?Ð?r   c               ó    € V ^8„  d   QhRRRR/# )r   r(   r)   r   Úboolr   )r   s   "r   r   r   �   s   € ÷ (ñ (˜jð (¨Tñ (r   c                ó4   € \        V 4      P                  4       # )u!  Whether any delivery was ever admitted for this profile (the mailbox directory is created on
first admission only). A cheap pre-check for pollers: no mailbox means nothing to claim, so the
owner lookup â€” a state.db open plus the exclusive active-session registry lock â€” can be skipped.)r�   Úis_dir)r(   s   &r   Úhas_mailboxr”   �   s   € ô �Ó×%Ñ%Ó'Ð'r   z	set[Path]Ú_warned_unhardenedÚ_warned_unusablec                  ó   € ] tR t^�tRtRtR# )ÚMailboxUnusablea¡  This token cannot list, create or lock inside the mailbox dir (#139485, #138872).

On Windows an elevated install/update creates ``runtime/bot_live_delivery`` owned by
Administrators with no entry for the user; the same user's non-elevated gateway then
cannot even open ``.lock``. Bot Chat deliveries pause; nothing else depends on the dir.
A ``PermissionError`` subclass so every existing caller keeps its handling.
r   NrD   r   r   r   r˜   r˜   �   s   † õr   r˜   c               ó    € V ^8„  d   QhRRRR/# )r   Úpathr
   r   r=   r   )r   s   "r   r   r   §   s   € ÷ ñ �Tð ˜cñ r   c                óT  € \         P                  R8X  dd    ^ RIp^ RIp TP                  \        T 4      TP                  4      pTP                  RTP                  4       4      w  rVpT'       d   T RT 2# T# ^ RIp V P                  4       P                  p	 TP                  T	4      P                   #   \         d   pRT R2u Rp?# Rp?ii ; i  TP                   d   pRT R2u Rp?# Rp?ii ; i  \         d   pRT R2u Rp?# Rp?ii ; i  \"         d	    RT	 2u # i ; i)zbBest-effort owner name for the log line; never raises (an ACL that hides it is the reported case).ÚntNz	unknown (Ú)Ú\zuid )ÚosÚnameÚ
pywintypesÚwin32securityÚImportErrorÚGetFileSecurityr=   ÚOWNER_SECURITY_INFORMATIONÚLookupAccountSidÚGetSecurityDescriptorOwnerÚerrorÚpwdÚstatÚst_uidÚOSErrorÚgetpwuidÚpw_nameÚKeyError)
rš   r¡   r¢   rt   Ú
descriptorr    ÚdomainÚ_r©   Úuids
   &         r   Ú
_dir_ownerr´   §   s(  € ä	‡w�w�$„ð	&ÛÛ ð	&Ø&×6Ñ6´s¸4³yÀ-×BjÑBjÓkˆJØ+×<Ñ<¸TÀ:×ChÑChÓCjÓk‰OˆD˜!÷ '-�&�˜˜D˜6Ð"Ð6°$Ð6Ûð"Ø�i‰i‹k× Ñ ˆðØ�|‰|˜CÓ ×(Ñ(Ð(øô ô 	&Ø˜s˜e 1Ð%Õ%ûð	&ûð
 ×Ñô 	&Ø˜s˜e 1Ð%Õ%ûð	&ûô ô "Ø˜3˜%˜qÐ!Õ!ûð"ûô ô Ø�c�Uˆ|Òðúsk   —B4  AC Á>C6 ÂD Â4CÂ?C
ÃCÃ
CÃC3Ã#C.Ã(C3Ã.C3Ã6DÄDÄDÄDÄD'Ä&D'c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úrootr
   rt   ÚPermissionErrorr   r˜   r   )r   s   "r   r   r   Á   s&   € ÷ `ñ `�Dð `˜ð `°?ñ `r   c                ó"  € \        V 4      pV \        9   d   \        P                  M\        P                  p\        P                  V 4       \        P                  VR V \        V 4      W4       \        VP                  RV 2\        V 4      4      # )z·bot_live_delivery: mailbox directory %s (owner %s) is not usable by this process (%s); Bot Chat deliveries are paused until it is repaired, other clients are unaffected. To repair, %sz%bot mailbox directory is not usable: )r   r–   ÚloggingÚDEBUGÚWARNINGÚaddÚlogr´   r˜   Úerrnor=   )r¶   rt   ÚremedyÚlevels   &&  r   Ú	_unusablerÁ   Á   su   € Ü  Ó&€FØ!Ô%5Ô5ŒG�MŠM¼7¿?¹?€EÜ×Ñ˜ÔÜ‡G�GˆEð oà”*˜TÓ" Cô1ô ˜3Ÿ9™9Ð(MÈcÈUÐ&SÔUXÐY]ÓU^Ó_Ð_r   c               ó    € V ^8„  d   QhRRRR/# )r   r¶   r
   r   r   )r   s   "r   r   r   Ë   s   € ÷ ñ �4ð ˜Dñ r   c                ó<  € V P                  4       '       * p\        V P                  RRR7       \        V RRR7        V P                  R4       V'       d5   \!        V P                  4       \!        V P                  P                  4       V R,          p\
        P"                  ! V\
        P$                  \
        P&                  ,          R	4      p\
        P(                  ! V4       V#   \         d«   p\
        P                  R8w  d4   T P                  4       P                  \
        P                  ! 4       8w  d   h T \        9   d   \        P                  M\        P                  p\        P                  T 4       \        P                  TRY4        Rp?ELHRp?ii ; i)
zLCreate/harden the mailbox dir and its ``.lock`` file; returns the lock path.T)ÚparentsÚexist_okiÀ  )ÚmoderÅ   rœ   z=bot_live_delivery: could not harden mailbox directory %s (%s)Nz.locké€  )r“   r   ÚparentÚchmodr¬   rŸ   r    rª   r«   Úgetuidr•   r¹   rº   r»   r¼   r½   r	   ÚopenÚO_CREATÚO_WRONLYr#   )r¶   Úcreatedrt   rÀ   ÚlockÚfds   &     r   Ú_preparerÑ   Ë   s  € à—+‘+“-Ô€GÜ�$—+‘+ t°dÕ;Ü�$˜U¨TÕ2ðcØ�
‰
�5Ô÷ ô 	˜Ÿ™Ô$Ü˜Ÿ™×*Ñ*Ô+Ø�'�>€DÜ	�Š�”r—z‘z¤B§K¡KÕ/°Ó	7€BÜ‡H‚HˆR„LØ€Køô' ô 	cä�7‰7�dŒ?˜tŸy™y›{×1Ñ1´R·Y²Y³[Ô@Øð "&Ô);Ô!;”—’ÄÇÁˆÜ×Ñ˜tÔ$Ü�‰�ÐVÐX\×bÒbûð	cús   ½C& Ã&FÃ1BFÆFc               ó   € V ^8„  d   QhRR/# )r   r   r)   r   )r   s   "r   r   r   é   s   € ÷ 
ñ 
�*ñ 
r   c           	   #  ó:  "  € \        V 4      p\        4       ;_uu_ 4       p VP                  \        \	        V4      4      4       \        P                  T4       Tx € RRR4       R#   \
         d   p\        Y4      ThRp?ii ; i  + '       g   i     R# ; i5i)z«Hold the mailbox dir lock. A dir this token cannot use raises ``MailboxUnusable``
(logged once per dir with its owner and the remedy); errors inside the body pass through.N)	r�   r   Úenter_contextr   rÑ   r·   rÁ   r–   Údiscard)r   r¶   Ústackrt   s   &   r   Ú_lockedr×   è   sy   é € ô �‹;€DÜ	�Œ˜ð	0Ø×Ñ¤	¬(°4«.Ó 9Ô:ô 	× Ñ  Ô&ØŠ
÷ 
‰øô ô 	0Ü˜DÓ&¨CÐ/ûð	0ú÷ 
�ˆüs?   ‚B B¢#A(ÁBÁ
BÁ(BÁ3A?Á?BÂBÂB	Â	Bc               ó    € V ^8„  d   QhRRRR/# ©r   rš   r
   r   r*   r   )r   s   "r   r   r   ö   s   € ÷ ñ �ð Ð.ñ r   c                ó  €  \         P                  ! V P                  RR7      4      p\	        T\
        4      '       g0   \        RT P                   R\        T4      P                   R24      hT#   \         d     R# i ; i)ua   Exact-id read: absent â†’ None; unreadable or not a JSON object â†’ raises (callers fail closed).ú	utf-8-sig©ÚencodingNzticket z is not a JSON object (r�   )
ÚjsonÚloadsÚ	read_textÚFileNotFoundErrorrz   r<   r;   r    ÚtyperE   ©rš   Úrecords   & r   Ú_readrå   ö   ss   € ðÜ—’˜DŸN™N°K˜NÓ@ÓAˆô �fœd×#Ò#Ü˜7 4§9¡9 +Ð-DÄTÈ&Ã\×EZÑEZÐD[Ð[\Ð]Ó^Ð^Ø€Møô	 ô Úðús   ‚&A/ Á/A>Á=A>Ú_warned_unreadablec               ó$   € V ^8„  d   QhRRRRRR/# )r   rš   r
   rä   rw   r   r   r   )r   s   "r   r   r     s!   € ÷ ñ ˜dð ¨Nð ¸zñ r   c                óÎ  a€ VP                  R4      oVP                  R4      VP                  RVP                  R4      4      r2VP                  R4      V P                  8w  g!   VP                  R4      V P                  8w  d   R# VP                  R4      p\        V\        4      '       d   VRR	0\        ,          9  d   R
V: 2# \
        ;QJ d    R W#3 4       F  '       d   K   RM	  RM! R W#3 4       4      '       g   R# \        S\        4      '       dI   \
        ;QJ d#    V3R l\         4       F  '       d   K   RM	  RM! V3R l\         4       4      '       g   R# R# )up  Why a parsed ticket is unusable by the scans, or None when it is well-formed.

A ticket that parses as JSON but lost a field (truncated rewrite, foreign
writer, hand edit) used to raise KeyError/TypeError out of the sequence
scan and the claim sweep â€” wedging admission and delivery for the whole
profile exactly like corrupt JSON did before ``_scan_read`` existed.
rv   Ú
created_atÚsequenceÚdelivery_idr   zid does not match filenameÚstatusÚqueuedÚclaimedzunknown status c              3  ó|   "  € T F2  p\        V\        4      ;'       d    \        V\        4      '       * x € K4  	  R # 5i©N)rz   Úintr‘   )r{   Úvs   & r   r~   Ú&_ticket_shape_error.<locals>.<genexpr>  s.   é € Ð^ÑG]À!Œz˜!œSÓ!×=Ð=¬*°Q¼Ó*=Ô&=Ô=ÓG]ùs   ‚<ž<FTz$created_at/sequence are not integersc              3  ó„   <"  € T F5  p\        SP                  V4      \        4      ;'       d
    SV,          x € K7  	  R # 5irð   )rz   r�   r=   )r{   Úkrv   s   & €r   r~   ró     s5   øé € Ð-nÑbmÐ]^¬j¸¿¹À1»ÄsÓ.K×.XÐ.XÐPUÐVWÕPXÔ.XÓbmùs
   ƒ*A ®A zowner pin is incompleteN)r�   Ústemrz   r=   Ú	_TERMINALr‚   r<   r€   )rš   rä   ré   rê   rì   rv   s   &&   @r   Ú_ticket_shape_errorrø     sü   ø€ ð �J‰J�wÓ€EØ!Ÿ:™: lÓ3°V·Z±ZÀ
ÈFÏJÉJÐWcÓLdÓ5e�Ø‡z�z�-Ó  D§I¡IÔ-°·±¸DÓ1AÀTÇYÁYÔ1NÙ+Ø�Z‰Z˜Ó!€FÜ�fœc×"Ò" f°hÀ	Ð5JÌYÕ5VÔ&WØ  ¡
Ð+Ð+ß‹3Ñ^È
ÑG]Ó^�3�3Š3Ñ^È
ÑG]Ó^×^Ò^Ù5Ü�eœT×"Ò"¯#«#Ô-nÕbmÓ-n¯#¯#ª#Ô-nÕbmÓ-n×*nÒ*nÙ(Ùr   c               ó    € V ^8„  d   QhRRRR/# rÙ   r   )r   s   "r   r   r     s   € ÷ ñ �Tð Ð3ñ r   c                óŽ  €  \        V 4      pVf   RM
\        W4      pVee   V \
        9   d   \        P                  M\        P                  p\
        P                  V 4       \        P                  VRV P                  V4       R# \
        P                  V 4       V#   \        \        3 d   pR\	        T4      r! Rp?L¡Rp?ii ; i)aà  Bulk-scan variant: one unreadable or malformed ticket must not wedge the whole dir.

Directory scans (sequence high-water mark, queued-claim sweep) may only
treat a file as absent when it is provably absent; an unreadable ticket
degrades to "that one delivery is uninspectable" with a warning.
Exact-id reads (admission idempotency, completion, result lookup) keep
using _read so a permission error still fails closed instead of
licensing an overwrite of a possibly-live receipt.
Nz5bot_live_delivery: skipping unreadable ticket %s (%s))rå   rø   r¬   r;   r=   ræ   r¹   rº   r»   r¼   r½   r    rÕ   )rš   rä   Úproblemrt   rÀ   s   &    r   Ú
_scan_readrü     s¡   € ð)Ü�t“ˆØ š.‘$Ô.AÀ$Ó.Oˆð ÒØ!%Ô);Ô!;”—’ÄÇÁˆÜ×Ñ˜tÔ$Ü�‰�ÐNÐPT×PYÑPYÐ[bÔcÙÜ×Ñ˜tÔ$Ø€Møô ”ZÐ ô )Ø¤ C£•ûð)ús   ‚B ÂCÂ.B?Â?Cc               ó    € V ^8„  d   QhRRRR/# )r   r¶   r
   r   rñ   r   )r   s   "r   r   r   4  s   € ÷ ñ ˜ð  #ñ r   c                ó,  a€ V \         ,          p \        VP                  RR7      4      p\        V3R lV P                  R4       4       ^ R7      p\        W#4      ^,           p\        V\        V4      RRR7       V#   \        \        3 d    ^ p Lgi ; i)	ab  Allocate the next admission sequence under the dir lock.

The high-water mark lives in a counter file beside the tickets, so a ticket
the scan cannot read does not drop its sequence and hand a later admission
a duplicate or lower one. Readable tickets still bootstrap dirs written
before the counter existed. Wall time can roll back; sequences never do.
rÛ   rÜ   c              3  óx   <"  € T F/  p\        V4      ;of   K  SP                  RSR,          4      x € K1  	  R # 5i)Nrê   ré   )rü   r�   )r{   Ú	candidaterä   s   & €r   r~   Ú!_next_sequence.<locals>.<genexpr>A  s<   øé € ð EÙ$7�yÜ!+¨IÓ!6Ð6�vô @�6—:‘:˜j¨&°Õ*>×?Ð?Û$7ùs   ƒ:™!:z*.json)ÚdefaultrÇ   T)rÆ   Ú	fsync_dir)	Ú_SEQUENCE_FILErñ   rà   r¬   r;   ÚmaxÚglobr   r=   )r¶   ÚcounterÚ	persistedÚscannedrê   rä   s   &    @r   Ú_next_sequencer
  4  s—   ø€ ð ”^Õ#€GðÜ˜×)Ñ)°;Ð)Ó?Ó@ˆ	ô ô EØ$(§I¡I¨hÔ$7óEàNOôQ€Gô �9Ó&¨Õ*€HÜ�gœs 8›}°5ÀDÕIØ€Oøô ”ZÐ ô ØŠ	ðús   �A= Á=BÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r   rš   r
   rä   rw   r   ÚNoner   )r   s   "r   r   r   I  s&   € ÷ ]ñ ]�ð ]˜~ð ]°$ñ ]r   c           	     ó&   € \        WR RRRR7       R # )NTrÇ   )ÚindentÚ	sort_keysr  rÆ   )r   rã   s   &&r   Ú_writer  I  s   € Ü�d¨4¸4È4ÐV[×\r   rë   ÚauthorÚnotification_categoryÚresultc               ó4   € V ^8„  d   QhRRRRRRRRR	R
RRRR/# )r   r(   r)   rv   rw   Úmessager=   rë   r   r  r*   r  r   r   )r   s   "r   r   r   M  sH   € ÷ >ñ >Øð>Ø%3ð>Ø>Að>àð>à/Dð>ð ð>ð ñ	>r   c          
     ó*   € \        \        WW#VVR7      # )zÝReturn durable admission immediately, without waiting for the owner.

Retry with the same id AND pinned owner/message to inspect the existing
state. Reusing an id with a different payload is an error, never an overwrite.
)rë   r  r  )Ú_doorrP   )r(   rv   r  rë   r  r  s   &&&$$$r   Údeliver_to_live_ownerr  M  s   € ô Ô# \¸'ÐciØ'<ô>ð >r   c               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r   r(   r)   rv   rw   r  r=   rë   r  r*   r   r   )r   s   "r   r   r   [  sB   € ÷ iñ i zð i¸.ð iÐSVð iÐhkð iØ!6ðiØBPñir   c          	     ó(   € \        \        WW#VR7      # )z¸Finalize a refusal marked ``admitted: false`` under the same identity: the owner's terminal
not-sent receipt (``refused``), or the receipt of an attempt that admitted the id meanwhile.)rë   r  )r  rR   )r(   rv   r  rë   r  s   &&&$$r   Úsettle_held_deliveryr  [  s   € ô Ô! <¸ÐagÔhÐhr   c               ó   € V ^8„  d   QhRR/# )r   ÚcallzCallable[[Path, dict], dict]r   )r   s   "r   r   r   b  s   € ÷ Rñ RÐ,ñ Rr   c               ó  € \        W4      p\        V\        4      '       g   \        R 4      hVR9  d   \        R4      h\	        V4      P                  4       pVR8X  d   RR/M/ p	/ T ! T\        RR\        Ve   TM\        P                  ! 4       P                  4      RVP                  P                  R8X  d   VP                  MRRV/VR	,          '       d   R	VR	,          /M/ BV'       d   R
\        V4      /M/ BV	B 4      CV	C# )zmessage must be a stringÚ
diagnosticzinvalid notification categoryr  r   ÚprofileÚprofilesr  r  r3   r  )r  r  r   )r…   rz   r=   r;   r
   r8   r<   rŠ   ÚuuidÚuuid4ÚhexrÈ   r    )
r  r(   rv   r  rë   r  r  r„   r   Úcategorys
   &&&&$$$   r   r  r  b  s%  € ä�LÓ(€FÜ�gœs×#Ò#ÜÐ3Ó4Ð4ØÐ$<Ô<ÜÐ8Ó9Ð9Ü�Ó×%Ñ%Ó'€DØ:OÐS_Ô:_Ð'¨Ñ6Ðeg€HðR‰d�4œñ D¤¸[Ò=T©kÔZ^×ZdÒZdÓZf×ZjÑZjÓ!kð DØ!Ÿ[™[×-Ñ-°Ô;�—	’	ÀðDàðDàDJÈ<×DXÔDX˜\¨6°,Õ+?Ñ@Ð^`ðD÷ (.ˆH”d˜6“lÑ#°2ðDð ;CñDó Eð Rð IQðRð Rr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r(   r)   rä   r<   r   r‘   r   )r   s   "r   r   r   s  s&   € ÷ Añ A zð A¸4ð AÀDñ Ar   c                ód   € \        V 4      pVRJ;'       g    \        VP                  R4      4      # )aO  Whether the profile authority still holds ``record`` (main's bounded DM wait asks this).

An admission lives in the authority's durable FIFO, so it is held while the authority is
reachable; an unreachable one raises (outcome unknown, never cancelled). Only an unadmitted
legacy record whose profile has no store is provably ownerless.
NÚadmission_id)rA   r‘   r�   )r(   rä   rv   s   && r   Úowner_holds_deliveryr)  s  s/   € ô & lÓ3€EØ˜Ð×@Ð@¤ V§Z¡Z°Ó%?Ó @Ð@r   c                ó   € R# )zäRetired UI poller: only session_bot may migrate and admit queued records.

Keep this refusal until the legacy notification poller's call site is removed.
A previously claimed record can still publish its terminal receipt below.
Nr   )r(   rv   s   &&r   Úclaim_pending_deliveryr+  ~  s   € ñ r   Úreplyr2   r¨   Úreasonc               ó4   € V ^8„  d   QhRRRRRRRRRRRRR	R
/# )r   r(   r)   rë   r=   rì   r,  r¨   r-  r   rw   r   )r   s   "r   r   r   ‡  sF   € ÷ ñ ØðØ+.ðØ;>ðàðàðà.1ðð ñr   c               ó¸  a
€ \        V4      pV\        9  d   \        R4      h\        W#WER7      p\	        V 4      ;_uu_ 4       pW† R2,          p	\        V	4      o
S
f   \        RV 24      hS
R,          \        9   dt   \        ;QJ d-    V
3R lVP                  4        4       F  '       g   K   RM"	  R	M! V
3R lVP                  4        4       4      '       d   \        R
4      hS
uuRRR4       # S
R,          R8w  d   \        R4      hS
P                  V\        P                  ! 4       R7       \        V	S
4       S
uuRRR4       #   + '       g   i     R# ; i)zNPersist an immutable terminal receipt; duplicate identical completion is safe.z invalid terminal delivery status)rì   r,  r¨   r-  ú.jsonNzdelivery not found: rì   c              3  óP   <"  € T F  w  rSP                  V4      V8g  x € K  	  R # 5irð   )r�   )r{   rõ   rò   rä   s   &  €r   r~   Ú$complete_delivery.<locals>.<genexpr>–  s    øé € ÐB±/©$¨!�6—:‘:˜a“= AÖ%³/ùs   ƒ#&TFz1delivery already has a different terminal receiptrî   z*delivery must be claimed before completion)Úcompleted_at)rŠ   r÷   r;   r<   r×   rå   rá   Úanyrƒ   ÚupdateÚtimeÚtime_nsr  )r(   rë   rì   r,  r¨   r-  r|   Úoutcomer¶   rš   rä   s   &&$$$$    @r   Úcomplete_deliveryr9  ‡  s	  ø€ ô
 �{Ó
#€CØ”YÔÜÐ;Ó<Ð<Ü˜&°UÔJ€GÜ	�×	Ô	 $Ø˜˜U�mÕ#ˆÜ�t“ˆØŠ>Ü#Ð&:¸3¸%Ð$@ÓAÐAØ�(ÕœyÔ(ß‹sÔB°'·-±-´/ÓB�s�sŠsÔB°'·-±-´/ÓB×BÒBÜ Ð!TÓUÐUØ÷ 
Ò	ð �(Õ˜yÔ(ÜÐIÓJÐJØ�‰�g¬D¯LªL«NˆÔ;Üˆt�VÔØ÷ 
×	×	Ó	ús&   ÁAEÂ	"EÂ.+EÃEÃ1AEÅE	c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r(   r)   rë   r=   r¨   r-  r   r*   r   )r   s   "r   r   r      s4   € ÷ ñ ØðØ+.ðØ:=ðØGJðàñr   c          
     ó|  € \        V4      p\        V 4      ;_uu_ 4       pWT R2,          p\        V4      pVe&   VR,          R8w  g   VP                  R4      '       d   VuuRRR4       # VP	                  RRW#\
        P                  ! 4       R7       \        Wg4       VuuRRR4       #   + '       g   i     R# ; i)	z“Cancel an ownerless queued receipt without racing a consumer's claim.

A claim or terminal result that won the mailbox lock is returned unchanged.
r0  Nrì   rí   r(  Ú	cancelledr2   )rì   r,  r¨   r-  r3  )rŠ   r×   rå   r�   r5  r6  r7  r  )r(   rë   r¨   r-  r|   r¶   rš   rä   s   &&$$    r   Úcancel_queued_deliveryr=     s˜   € ô �{Ó
#€CÜ	�×	Ô	 $Ø˜˜U�mÕ#ˆÜ�t“ˆàŠ>˜V HÕ-°Ô9¸V¿Z¹ZÈ×=WÒ=WØ÷ 
Ò	ð 	�‰˜[°¸%Ü#'§<¢<£>ð 	ô 	3äˆtÔØ÷ 
×	×	Ó	ús   Ÿ?B*ÁB*Á+4B*Â*B;	c               ó$   € V ^8„  d   QhRRRRRR/# ©r   r(   r)   rë   r=   r   r*   r   )r   s   "r   r   r   ´  s"   € ÷ ñ  zð Àð ÐH]ñ r   c                óV  € \        V4      p\        V 4      P                  4       '       g   R# \        V 4      ;_uu_ 4       p\	        W2 R2,          4      pRRR4       Xe6   VP                  R4      '       d   VP                  R4      R8X  d	   / VCRR/C# V#   + '       g   i     LK; i)zLRead admission/claim/terminal state without waiting or deleting its receipt.Nr0  r(  rì   r4   rí   )rŠ   r�   r“   r×   rå   r�   )r(   rë   r|   r¶   rä   s   &&   r   Úread_delivery_resultrA  ´  s‘   € ä
�{Ó
#€CÜ�Ó×%Ñ%×'Ò'Ùô 
�×	Ô	 $Ü�t  U˜mÕ+Ó,ˆ÷ 
àÒ˜fŸj™j¨×8Ò8¸V¿Z¹ZÈÓ=QÐU`Ô=`ð .�&Ð-˜( HÑ-Ð-Ø€M÷ 
×	ús   Á BÂB(	g      à?c               ó$   € V ^8„  d   QhRRRRRR/# r?  r   )r   s   "r   r   r   È  s"   € ÷ ñ  
ð ¸ð ÐAVñ r   c                ó˜   € \        \        V 4      \        V4       R2,          4      pVe   VP                  R4      R8X  d	   / VCRR/C# V# )a  A waiter's read: the receipt file the owner republishes when the admission settles (and on
restart recovery). Never an authority RPC: a wait outlives owner restarts, and replaying the
envelope (``read_delivery_result``) is for producers re-confirming their admission.r0  rì   r4   rí   )rå   r�   rŠ   r�   )r(   rë   rä   s   && r   Ú_poll_receiptrD  È  sR   € ô ”5˜Ó&¬L¸Ó,EÐ+FÀeÐ)LÕLÓM€FØÒ˜fŸj™j¨Ó2°kÔAà-�&Ð-˜( HÑ-Ð-Ø€Mr   Úshould_stopc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# ©r   r(   r)   rë   r=   r/   zfloat | NonerE  zCallable[[], bool] | Noner   r*   r   )r   s   "r   r   r   Ó  s=   € ÷ Zñ ZØðZØ+.ðZØ9EðZà-ðZð ñZr   c               ór  € Vf   RM\         P                  ! 4       V,           p \        W4      pVe   VR,          \        9  d   V# Ve   V! 4       '       d   V# Vf   RMV\         P                  ! 4       ,
          pVe
   V^ 8:  d   V# \         P                  ! Vf   \
        M\        \
        V4      4       K–  )uk  Poll a receipt until the owner settles it, ``timeout`` lapses, or ``should_stop`` says so.

Every transport that hands a turn to a live Bot Chat owner (local ``message_agent``, the
Desktop relay, ``hermes peer dm`` and ``hermes peer run``) waits on the same receipt; keeping
the loop here is what stops the lanes drifting (one lane returned a receipt sentence instead
of the reply, two never waited at all). Returns the last record read â€” still pending when the
budget lapsed, None when the receipt was never readable. Polls the local receipt file only, so
an owner restart mid-wait is just a longer pending stretch.
Nrì   )r6  Ú	monotonicrD  Ú_PENDINGÚsleepÚ_POLL_SECONDSÚmin)r(   rë   r/   rE  Údeadlinerä   Ú	remainings   &&&$   r   Úawait_deliveryrP  Ó  s’   € ð ’‰t¬D¯NªNÓ,<¸wÕ,F€HØ
Ü˜|Ó9ˆØŠ>˜V HÕ-´XÔ=ØˆMØÒ"¡{§}¢}ØˆMØ$Ò,‘D°(¼T¿^º^Ó=MÕ2Mˆ	ØÒ  Y°!¤^ØˆMÜ�
Š
 IÒ$5•=¼3¼}ÈiÓ;XÖYr   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# rG  r   )r   s   "r   r   r   í  s=   € ÷ cñ cØðcØ+.ðcØ9Eðcà-ðcð ñcr   c             ƒ  ó¶  "  € ^ RI pVf   RM\        P                  ! 4       V,           p VP                  \        W4      G Rj  x€L
 pVe   VR,          \
        9  d   V# Ve   V! 4       '       d   V# Vf   RMV\        P                  ! 4       ,
          pVe
   V^ 8:  d   V# TP                  Vf   \        M\        \        V4      4      G Rj  x€L
  K¬   L‘ L5i)zX``await_delivery`` for an event loop: never blocks a worker thread for the whole budget.Nrì   )	rg   r6  rI  r_   rD  rJ  rK  rL  rM  )r(   rë   r/   rE  rg   rN  rä   rO  s   &&&$    r   Úawait_delivery_asyncrS  í  s¶   é € ó
 à’‰t¬D¯NªNÓ,<¸wÕ,F€HØ
Ø×(Ñ(¬¸ÓR×RˆØŠ>˜V HÕ-´XÔ=ØˆMØÒ"¡{§}¢}ØˆMØ$Ò,‘D°(¼T¿^º^Ó=MÕ2Mˆ	ØÒ  Y°!¤^ØˆMØ�m‰m¨YÒ->�MÄCÌÐW`ÓDaÓb×bÒbñ Sñ 	cùs+   ‚ACÁCÁ,CÁ1ACÃCÃCÃC)r(   r3   r5   r6   >   ÚfailedÚsettledÚ	ambiguousr<  )rí   rî   )KÚ__conditional_annotations__rI   Ú
__future__r   rÞ   r¹   rŸ   rˆ   r6  r"  Ú
contextlibr   r   Úhermes_dir_aclr   r   Úutilsr   r   r	   Úpathlibr
   Útypingr   r   Úhermes_cli.active_sessionsr   Ú	getLoggerrE   r½   rŽ   r  r€   Ú	frozensetr÷   r&   rA   r;   rC   rP   rR   rM   r…   rŠ   r�   r”   Úsetr•   Ú__annotations__r–   r·   r˜   r´   rÁ   rÑ   r×   rå   ræ   rø   rü   r
  r  r  r  r  r)  r+  r9  r=  rA  rJ  rL  rD  rP  rS  )rW  s   @r   Ú<module>rc     sÍ  øðôõ #ã Û Û 	Û 	Û Û ß 0ß =ç GÑ GÝ ß  å 0à×Ò˜Ó!€à'Ð Ø€ØK€ÙÒEÓF€	õõTô&c�:ô cò=ò
<ò%õPõõ@õ(ñ !$£Ð �IÓ %ñ "›eÐ �)Ó #ô�oô õõ4`õð: ô
ó ð
õñ !$£Ð �IÓ %õõ,õ0õ*]ð>à!%ð>àGKð>ð "*÷>ðiØ9=÷iðRÐ[_ð RÐhlð RØ (÷Rõ"Aòðàðà"$ðà46÷õ2õ(ð  !€Ø€õðZà04÷Zð4cà04÷cñ cr   