+
    lHàjR¹  ã                  óä  a € 0 t $ R t^ RIHt ^ RIt^RIHt R tR R ltR R lt	RwR	 R
 llt
RwR R lltR R ltR R ltR R ltR R ltRRxRRyRRzRRz/tR R ltR{tR!;ttR" R# ltR$ R% ltR& R' ltR(t]tR) R* ltR+ R, ltR- R. ltR/ R0 ltR1 R2 ltR3 R4 ltR5 R6 lt R7 R8 lt!R9 R: lt"R; R< lt#R= R> lt$R? R@ lt%RA RB lt&RC RD lt'RRE]&3RRFRG 3RRHRI 3RRHRJ 3RRK]'3R RLRM 3/t(RN RO lt)RP RQ lt*RR RS lt+RT RU lt,RV RW lt-RX RY lt.RwRZ lt/R[ R\ lt0R] R^ lt1RwR_R`/Ra Rb lllt2Rc t3R_R`/Rd lt4Re Rf lt5Rg Rh lt6Ri Rj lt7R`s8Rk Rl lt9. t:Rm];Rn&   Ro Rp lt<Rq Rr lt=Rs Rt lt>Ru Rv lt?R# )|a  Per-session notification poller: kanban/loop/delegation events routed to the owning session,
desktop UI wiring, HUD surface note. Bodies are rebound onto server.py's globals at install time
(method_ctx.bind_module), so they reference server.py globals bare.)ÚannotationsN)Úbind_modulec                óœ   €  \         ;_uu_ 4        V ! \        4      uuRRR4       #   + '       g   i     R# ; i  \         d    Tu # i ; i)zaRun ``fn(_sessions)`` under ``_sessions_lock``; ``default`` on failure (poller must never crash).N)Ú_sessions_lockÚ	_sessionsÚ	Exception)ÚfnÚdefaults   &&ÚF/home/ubuntu/.hermes/hermes-agent/tui_gateway/session_notifications.pyÚ_notif_locked_sessionsr      s2   € ðßŽ^Ù”i“=÷ �^�^‹^ûäô ØŠðús#   ‚; �'œ
; §8	²; ¸; »AÁ
Ac               ó$   € V ^8„  d   QhRRRRRR/# )é   ÚsidÚstrÚsessionÚdictÚreturnÚset© )Úformats   "r
   Ú__annotate__r      s&   € ÷ _ñ _˜Sð _¨4ð _°Cñ _ó    c                ób   € \        VP                  R 4      ;'       g    R4      \        WR7      0# ©Úsession_keyÚ )Úfallback©r   ÚgetÚ_session_lookup_key©r   r   s   &&r
   Ú_notif_current_keysr!      s)   € Ü�—‘˜MÓ*×0Ð0¨bÓ1Ô3FÀwÔ3]Ð^Ð^r   c               ó    € V ^8„  d   QhRRRR/# )r   Úsr   r   Úboolr   )r   s   "r
   r   r      s   € ÷ bñ b˜dð b¨Tñ br   c                ó€   € \        V P                  R 4      ;'       g    R4      V9   ;'       g    \        V RR7      V9   # r   r   )r#   Úkeyss   &&r
   Ú_notif_session_matchesr'      s:   € Üˆq�u‰u�]Ó#×)Ð) rÓ*¨dÑ2×aÐaÔ6IÈ!ÐVXÔ6YÐ]aÑ6aÐar   c               ó    € V ^8„  d   QhRRRR/# )r   Úexcludeúdict | Noner   r$   r   )r   s   "r
   r   r      s   € ÷ ñ ¨{ð Àdñ r   c                ó(   a a€ \        VV 3R lR4      # )z•Any non-finalized live session (other than ``exclude``) matches ``keys``; False if the registry can't be read
(fail open rather than drop the event).c                ó´   <€ \         ;QJ d.    VV3R  lV P                  4        4       F  '       g   K   R# 	  R# ! VV3R  lV P                  4        4       4      # )c              3  ó�   <"  € T F;  pVSJ;'       d+    VP                  R 4      '       * ;'       d    \        VS4      x € K=  	  R# 5i)Ú
_finalizedN)r   r'   )Ú.0r#   r)   r&   s   & €€r
   Ú	<genexpr>Ú@_notif_live_session_matches.<locals>.<lambda>.<locals>.<genexpr>!   sF   øé € ð -Ù +˜1ð  Ð'×gÐg°·±°lÓ0CÔ,C×gÐgÔH^Ð_`ÐbfÓHgÔgÛ +ùs   ƒA“A±ATF)ÚanyÚvalues)Ússr)   r&   s   &€€r
   Ú<lambda>Ú-_notif_live_session_matches.<locals>.<lambda>!   sD   ø€ —3“3õ -Ø "§	¡	¤ó-—3”3ð -’3ð -�3õ -Ø "§	¡	¤ó-ô -r   F)r   )r&   r)   s   ffr
   Ú_notif_live_session_matchesr7      s   ù€ ô "õ	-àóð r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úevt_keyr   r   r*   r   r   )r   s   "r
   r   r   &   s!   € ÷ ñ  cð °Kð È3ñ r   c                óä   €  \        T;'       g    / 4      ;_uu_ 4       pVe   VP                  V 4      MT ;'       g    T uuRRR4       #   + '       g   i     R# ; i  \         d    T u # i ; i)záResolve a compression-rotated session key to its continuation tip (or itself). Looked up in
``session``'s own store: a named-profile session's lineage lives in ``profiles/<x>/state.db``,
where the launch handle cannot see it.N)Ú_session_dbÚresolve_resume_session_idr   )r9   r   Údbs   && r
   Ú_notif_resolve_event_keyr>   &   sZ   € ðÜ˜Ÿ˜ B×'Ô'¨2Ø=?º^�B×0Ñ0°Ô9ÐQX×dÐdÐ]d÷ (×'×'Ó'ûäô ØŠðús8   ‚A �A ŸA¾AÁ 
A ÁA	ÁA ÁA ÁA/Á.A/c               ó(   € V ^8„  d   QhRRRRRRRR/# ©r   r   r   r   r   Úevtr   r$   r   )r   s   "r
   r   r   1   s/   € ÷ Qñ Q¨sð Q¸Tð QÈð QÐQUñ Qr   c                ó  a€ \        VP                  R4      ;'       g    R4      oS'       dL   S\        T ;'       g    R4      8X  d   VP                  R4      '       g   R# \        V3R lR4      '       d   R# \        VP                  R4      ;'       g    R4      pV'       g   R# \        W4      p\	        W14      pWS8w  d   WT9   d   R# \        V04      '       d   R# W49   d   R# WS8X  d   \        WV4      '       d   R# \        W50VR7      # )	zãTrue if ``evt`` is owned by a *different* live session. Background completions carry the ``session_key`` of the
session that started the work; async delegation completions also carry ``origin_ui_session_id`` (the live TUI tab).Úorigin_ui_session_idr   r.   Fc                óX   <€ SV 9   ;'       d    V S,          P                  R 4      '       * # )r.   ©r   )r4   Ú
evt_ui_sids   &€r
   r5   Ú7_notification_event_belongs_elsewhere.<locals>.<lambda>8   s(   ø€ ¨Z¸2Ñ-=×-fÐ-fÀbÈÅn×FXÑFXÐYeÓFfÔBfÐ-fr   Tr   )r)   )r   r   r   r!   r>   r7   Ú!_notif_other_profile_session_owns)r   r   rA   r9   Úcurrent_keysÚresolved_keyrF   s   &&&   @r
   Ú%_notification_event_belongs_elsewhererK   1   sá   ø€ ô �S—W‘WÐ3Ó4×:Ð:¸Ó;€JßØœ˜SŸY˜Y B›Ô'°·±¸L×0IÒ0IÙÜ!Ô"fÐhm×nÒnÙô �#—'‘'˜-Ó(×.Ð.¨BÓ/€GßÙÜ& sÓ4€Lô ,¨GÓ=€LØÔØÔ'ÙÜ&¨ ~×6Ò6ÙØÔÙØÔÔ#DÀSÐSV×#WÒ#WÙÜ&¨Ð'>ÈÔPÐPr   c               ó(   € V ^8„  d   QhRRRRRRRR/# r@   r   )r   s   "r
   r   r   P   s.   € ÷ kñ k¨3ð k¸ð kÀDð kÈTñ kr   c                óæ   aaa€ \        SP                  R4      ;'       g    R4      o\        VV3R l. 4      p\        ;QJ d    V3R lV 4       F  '       g   K   R# 	  R# ! V3R lV 4       4      # )aƒ  True when a live session on ANOTHER profile store provably owns ``evt`` (its compression lineage
resolves there). Every poller drains one process-wide queue, but lineage is looked up in the
dequeuer's own store; without this, profile B dequeuing an event keyed on profile A's compressed
parent found no owner anywhere and dropped it for good. Snapshot under the lock, resolve outside it.Úprofile_homer   c           	     óò   <€ V P                  4        UUu. uFT  w  rVSJg   K  VP                  R 4      '       d   K&  \        VP                  R4      ;'       g    R4      S8w  g   KQ  W3NKV  	  upp# u uppi )r.   rN   r   )Úitemsr   r   )r4   Ú	other_sidÚotherÚown_homer   s   &  €€r
   r5   Ú3_notif_other_profile_session_owns.<locals>.<lambda>W   sm   ø€ ¸r¿x¹x¼zô J¹zÑ+;¨9Ø GÐ+ô 'Ø49·I±I¸l×4Kô 'ä˜EŸI™I nÓ5×;Ð;¸Ó<ÀÑHô '�YÓ&¹zó Jùó Js   •
A3¤A3½A3Á	A3Á(A3c              3  ó@   <"  € T F  w  r\        WS4      x € K  	  R # 5i©N)Ú _session_owns_notification_event)r/   rQ   rR   rA   s   &  €r
   r0   Ú4_notif_other_profile_session_owns.<locals>.<genexpr>[   s!   øé € ÐjÑ_iÑK[È9Ô/°	À#×FÐFÓ_iùs   ƒTF)r   r   r   r2   )r   r   rA   Ú
candidatesrS   s   &ff @r
   rH   rH   P   sb   ú€ ô
 �7—;‘;˜~Ó.×4Ð4°"Ó5€HÜ'õ	Jð 	ó	€J÷
 ‹3ÔjÑ_iÓj�3Œ3ÐjŠ3Ðjˆ3ÔjÑ_iÓjÓjÐjr   c               ó(   € V ^8„  d   QhRRRRRRRR/# r@   r   )r   s   "r
   r   r   ^   s.   € ÷ uñ u¨#ð u¸ð uÀ4ð uÈDñ ur   c                ó2  € VP                  R4      '       d   R# VP                  R4      R8X  dP   VP                  R4      '       d9   \        V4      '       g(   \        '       d   VP                  R4      \        J g   R# \	        VP                  R4      ;'       g    R4      \	        T ;'       g    R4      8X  d   R	# \	        VP                  R
4      ;'       g    R4      p\        W4      p\        V4      ;'       d    W49   ;'       g    \        W14      V9   # )uà   True iff *this* session PROVABLY owns ``evt`` (UI origin is this live session, or ``session_key`` raw/compression-
resolved matches) â€” the fail-closed gate for addressed notifications, without the orphan-adoption fallback.r.   FÚtypeÚasync_delegationÚstartup_replayÚ	transportrC   r   Tr   )r   Ú_session_has_live_transportÚ_stdio_is_rpc_channelÚ_stdio_transportr   r!   r$   r>   )r   r   rA   r9   rI   s   &&&  r
   rW   rW   ^   sØ   € ð ‡{�{�<× Ò Ùð 	�‰�‹Ð-Ô-°#·'±'Ð:J×2KÒ2KÜ0°×9Ò9ß.Ó.°7·;±;¸{Ó3KÔO_Ó3_ÙÜ
ˆ3�7‰7Ð)Ó*×0Ð0¨bÓ1´S¸¿¸À³^ÔCÙÜ�#—'‘'˜-Ó(×.Ð.¨BÓ/€GÜ& sÓ4€LÜ�‹=×tÐt˜gÑ5×sÐsÔ9QÐRYÓ9cÐgsÑ9sÐtr   c               ó    € V ^8„  d   QhRRRR/# )r   rA   r   r   r$   r   )r   s   "r
   r   r   s   s   € ÷ tñ t¨Dð t°Tñ tr   c                ó    € V P                  R4      R8H  ;'       g4    \        V P                  R4      ;'       g    V P                  R4      4      # )z?Whether ``evt`` must be positively claimed before TUI delivery.r\   r]   rC   r   )r   r$   )rA   s   &r
   Ú"_notification_event_requires_ownerre   s   sB   € à�7‰7�6‹?Ð0Ñ0×sÐs´D¸¿¹ÐAWÓ9X×9rÐ9rÐ\_×\cÑ\cÐdqÓ\rÓ4sÐsr   Úwatch_matchÚ	heartbeatÚwatch_disabledÚwatch_overflow_c               ó    € V ^8„  d   QhRRRR/# )r   rA   r   r   Útupler   )r   s   "r
   r   r   ‚   s   € ÷ oñ o tð o°ñ or   c                óF  a € S P                  RR4      pVR9   d4   S P                  R4      '       d   S P                  RR4      VS R,          3# VR8X  d   S P                  R4      '       dT   S P                  R4      ;'       g    / .^ ,          ;'       g    / P                  R	R4      pS P                  R
R4      VRV3# S P                  R
R4      V3# \        P                  VP                  R4      '       d   RMTR4      pS P                  RR4      V.V 3R lV 4       O5# )z6UI-emission identity for a process notification event.r\   Ú
completionÚevent_idÚ
session_idr   r]   Útask_failure_noticeÚresultsÚ
task_indexÚdelegation_idÚtask_failureri   c              3  óX   <"  € T F  pSP                  YR 8X  d   ^ MR4      x € K!  	  R# 5i)Ú
suppressedr   NrE   )r/   ÚfrA   s   & €r
   r0   Ú0_notification_event_dedup_key.<locals>.<genexpr>�   s*   øé € Ð2mÑglÐbc°3·7±7¸1ÈÔCT¹aÐZ\×3]Ð3]Óglùs   ƒ'*>   rf   rh   r   )r   Ú_DEDUP_EXTRA_FIELDSÚ
startswith)rA   Úevt_typeÚtask_idxÚextras   f   r
   Ú_notification_event_dedup_keyr~   ‚   s  ø€ à�w‰w�v˜|Ó,€HØÐ4Ô4¸¿¹À×9LÒ9LØ—‘˜ bÓ)¨8°S¸µ_ÐEÐEØÐ%Ô%ð �7‰7Ð(×)Ò)ØŸ™ Ó+×3Ð3°¨t°QÕ7×=Ð=¸2×BÑBÀ<ÐQSÓTˆHØ—G‘G˜O¨RÓ0°(¸NÈHÐUÐUØ—‘˜¨Ó,¨hÐ7Ð7Ü×#Ñ#¸×9LÑ9LÐM^×9_Ò9_Ñ$5ÐemÐoqÓr€EØ�G‰G�L "Ó% xÐnÔ2mÑglÓ2mÑnÐnr   Ú	completedÚblockedÚgave_upÚcrashedÚ	timed_outÚstatusg      @c               ó    € V ^8„  d   QhRRRR/# ©r   r   r   r   ÚNoner   )r   s   "r
   r   r   š   s   € ÷ #ñ # ð #¨$ñ #r   c                ól   € V R ,          ;_uu_ 4        RV R&   RRR4       R#   + '       g   i     R# ; i)Úhistory_lockFÚrunningNr   )r   s   &r
   Ú_notif_release_turnr‹   š   s&   € Ø	�×	 ×	 Ø"ˆ�	Ñ÷ 
!×	 ×	 Ò	 ús   ’"¢3	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                óô   € \        V 4      ;_uu_ 4       pV'       d/   V P                  R4      '       g   V P                  R4      '       d    RRR4       R# RV R&    RRR4       R#   + '       g   i     R# ; i)zçClaim the idle session (running=True) under history_lock; False if a turn is live.
After the user's Stop no automatic turn starts: the cancel latch holds notifications
(requeued by the callers) until the next user prompt clears it.rŠ   Ú_turn_cancel_requestedNFT)Ú_session_turn_admissionr   )r   Úadmitteds   & r
   Ú_notif_claim_turnr’   Ÿ   sZ   € ô 
! ×	)Ô	)¨Xß˜7Ÿ;™; y×1Ò1°W·[±[ÐAY×5ZÒ5ZØ÷ 
*Ñ	)ð "ˆ�	ÑØ÷	 
*×	)×	)Ò	)ús   ”A&´A&ÁA&ÁA&Á&A7	c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úwhatr   ÚexcÚBaseExceptionr   r‡   r   )r   s   "r
   r   r   ª   s&   € ÷ Qñ Q˜Sð Q }ð Q¸ñ Qr   c                ót   € \        R V  R\        V4      P                   RV 2\        P                  R7       R# )z[tui_gateway] ú: )ÚfileN)Úprintr\   Ú__name__ÚsysÚstderr)r”   r•   s   &&r
   Ú_notif_log_failurerž   ª   s.   € Ü	ˆN˜4˜& ¤4¨£9×#5Ñ#5Ð"6°b¸¸Ð
>ÄSÇZÁZ×Pr   ç      Ð?c               ó    € V ^8„  d   QhRRRR/# r†   r   )r   s   "r
   r   r   µ   s   € ÷ ñ  Dð ¨Tñ r   c                ó¢   € V P                  R4      ;'       g    \        p\        V^,          \        4      V R&   \        P                  V4       R# )zUWait before requeueing a refused notice: this session's next delay doubles, to a cap.Ú_notif_refusal_delayN)r   Ú_NOTIF_REFUSAL_BACKOFF_SÚminÚ_NOTIF_REFUSAL_BACKOFF_MAX_SÚtimeÚsleep)r   Údelays   & r
   Ú_notif_refusal_backoffr©   µ   s=   € à�K‰KÐ.Ó/×KÐKÔ3K€EÜ&)¨%°!­)Ô5QÓ&R€GÐ"Ñ#Ü‡J�JˆuÖr   c               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# )
r   Úridr   r   r   r   Útextr”   r   r$   r   )r   s   "r
   r   r   ¼   s7   € ÷ ñ �sð  ð ¨tð ¸3ð Àcð ÐX\ñ r   c                óÄ   €  \        WW#3/ VB pV'       d   VP                  RR4       V# \        V4       V#   \         d   p\	        YG4       \        T4       h Rp?ii ; i)zDOnly the execution gate can acknowledge a claimed notification turn.r¢   N)Ú_run_prompt_submitÚpopr‹   r   rž   )r«   r   r   r¬   r”   ÚkwargsÚacceptedr•   s   &&&&&,  r
   Ú_notif_submitr²   ¼   sc   € ðÜ% c°ÑHÀÑHˆßØ�K‰KÐ.°Ô5ð
 ˆô   Ô(ØˆøÜô Ü˜4Ô%Ü˜GÔ$Øûðús   ‚(8 «8 ¸AÁAÁAc               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   r¬   r   r‡   r   )r   s   "r
   r   r   Í   s&   € ÷ @ñ @˜Cð @ sð @¨tñ @r   c                ó(   € \        R V RRRV/4       R# )ústatus.updateÚkindÚloopr¬   N©Ú_emit©r   r¬   s   &&r
   Ú_notif_loop_statusr»   Í   s   € Ü	ˆ/˜3 ¨°¸Ð >Ö?r   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r«   r   r   r   r   Úwakeupr   r‡   r   )r   s   "r
   r   r   Ñ   s0   € ÷ 4ñ 4 ð 4¨#ð 4¸ð 4È3ð 4ÐSWñ 4r   c           	     óV  € \        V4        VP                  4       R,          P                  R^4      p\        R,          ! T RV'       d
   V^ ,          MRR\	        V4      ^8”  d
   V^,          MRRV/4      pT;'       g    / P                  R4      ;'       g    / p\        VP                  R	4      ;'       g    R4      P                  4       ;p'       d   \        W4       VP                  R
4      R8X  d\   VP                  R4      '       dE   \        V4      '       g   VP                  4        \        W4       R# \        WW'R,          R4       R# TP                  R4      p	T	P                  R4      '       d   \        YR,          4       \        Y4       R#   \         d     LTi ; i)u  Slash-command /loop wakeup: route through the slash pipeline, not the model. No model reply to evaluate, so the
tick completes immediately â€” unless the command resolves to a prompt (skill command etc.), which runs as a normal
turn whose post-turn hook completes the tick.:é   NNNzcommand.dispatchÚnamer   Úargro   ÚresultÚoutputr\   ÚsendÚmessagezloop wakeup send failed)r‹   ÚlstripÚsplitÚ_methodsÚlenr   r   Ústripr»   r’   Úabandon_tickÚ!_publish_session_control_snapshotr²   r   Úcomplete_tick)
r«   r   r   Úmgrr½   ÚpartsÚrespÚpayloadÚoutÚdecisions
   &&&&&     r
   Ú_notif_slash_loop_tickrÔ   Ñ   s]  € ô ˜Ô ðØ—‘“ Õ#×)Ñ)¨$°Ó2ˆÜÐ*Ö+Ø�&§e˜% ž(°°UÌÈEË
ÐUVÌ¸EÀ!¾HÐ\^Ð`lÐnqÐrótˆà—:�:˜2×"Ñ" 8Ó,×2Ð2°ˆÜ�g—k‘k (Ó+×1Ð1¨rÓ2×8Ñ8Ó:Ð:ˆ3Ö:Ü˜sÔ(Ø�;‰;�vÓ &Ô(¨W¯[©[¸×-CÒ-CÜ$ W×-Ò-Ø× Ñ Ô"Ü1°#Ô?Ùä˜# G°YÕ-?ÐAZÔ[Ùð × Ñ  Ó$€HØ‡|�|�I×ÒÜ˜3¨Õ 3Ô4Ü% cÖ3øô ô Ùðús6   �A3F ÂF ÂF Â:F Ã7F Ä,F Ä=F ÆF(Æ'F(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!   € ÷ ñ ¨4ð ¸cð Àdñ r   c                óÈ  €  \        V 4      ;_uu_ 4       pV\        4       3 Uu/ uF  q3f   K  \        V4      VbK  	  upP                  4        F\  pVP	                  V4      ;pf   K  \        VP                  R4      4      ;'       d    VP                  R4      '       * u uuRRR4       # 	  RRR4       R# u upi   + '       g   i     R# ; i  \         d     R# i ; i)aË  Whether the gateway's heartbeat poller owns this session's due tick.

Desktop/TUI can attach to a messaging conversation, but its session-owner poller has no adapter
route for the reply. Ownership is the gateway's LIVE routing index, not the row's immutable
``source``: ``gateway/run_heartbeat_restore.py`` only registers watches for a non-suspended,
origin-bearing key whose current ``session_id`` is this one, so a row archived by /reset,
auto-reset or compression rotation belongs to nobody there and must keep firing here. The index
lives in the gateway's home store (the launch handle for a multiplexed gateway, the profile's
own store for a per-profile gateway), so both are consulted; no entry is fail-open.
NÚoriginÚ	suspendedF)r;   Ú_get_dbÚidr3   Ú!gateway_routing_entry_for_sessionr$   r   r   )r   r   r=   ÚdÚstoreÚentrys   &&    r
   Ú_notif_gateway_owns_heartbeatrß   í   s¹   € ðÜ˜×!Ô! RØ-/´³©OÓM©O qœ(œ"˜Q›% š(©OÑM×TÑTÖV�Ø"×DÑDÀ[ÓQÐQ�EÔ^Ü §	¡	¨(Ó 3Ó4×SÐS¸U¿Y¹YÀ{Ó=SÔ9SÑS÷ "Ò!ÙV÷ "ñ ùò N÷ "Ö!ñ ûÜô Úðús[   ‚C •B>¤B9®B9¾&B>Á) B>Â
B>Â"
C Â-B>Â/C Â9B>Â>C	Ã	C ÃC ÃC!Ã C!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!   € ÷ "ñ "¨ð "°dð "¸tñ "r   c           
     ót  €  ^ RI Hp TP                  R4      ;'       g    R;p'       g   R# T! TR7      pTP	                  4       '       d2   TP
                  P                  4       '       d   \        Y4      '       d   R# \        T4      '       g   R# TP                  4       ;p'       g   \        T4       R# Rp \        RT RR	R
RTP
                  P                   R2/4       \        \        R\        \         P!                  4       R,          4       2YT4      4      pT'       gI   \        T4       \$        P&                  ! \        4      ;_uu_ 4        TP)                  4        RRR4       R# R#   \         d     R# i ; i  \         d   p\#        RT4        Rp?L€Rp?ii ; i  + '       g   i     R# ; i)ua  Fire a due /heartbeat prompt for an idle TUI/Desktop/dashboard session (#102056, #103044).

``/heartbeat`` runs in the slash worker, whose CLI watchdog queues the due prompt into a
``_pending_input`` no turn loop ever drains â€” armed-but-dead. State is durable in SessionDB, so
the session-owner process drives firing exactly like ``_maybe_fire_tui_loop_tick``: claim the
idle session first (a racing user prompt wins), then re-enter through ``_run_prompt_submit`` as a
plain user turn. A dispatch that never starts a turn rewinds the persisted fire so the tick stays
due instead of being silently consumed.
©ÚHeartbeatManagerNr   r   ©ro   Frµ   r¶   rg   r¬   u   â™¥ heartbeat #õ
    firingâ€¦Ú__heartbeat__éè  zheartbeat dispatch failed)Úhermes_cli.heartbeaträ   r   r   Ú	is_activeÚstateÚis_duerß   r’   Ú
due_promptr‹   r¹   Ú
fire_countr$   r®   Úintr¦   rž   Ú
contextlibÚsuppressÚabandon_fire)r   r   rä   Úsid_keyrÎ   ÚpromptÚstartedr•   s   &&      r
   Ú_maybe_fire_tui_heartbeat_tickrö     sg  € ðÝ9ð —{‘{ =Ó1×7Ð7°RÐ7ˆGÖ7ÙÙ
 gÔ
.€CØ�=‰=�?Š? #§)¡)×"2Ñ"2×"4Ò"4Ô8UÐV]×8gÒ8gÙÜ˜W×%Ò%ÙØ—n‘nÓ&Ð&ˆFÖ&Ü˜GÔ$ÙØ€Gð=Üˆo˜s V¨[¸&ÀOÐTW×T]ÑT]×ThÑThÐSiÐisÐBtÐ$uÔvÜÔ)¨M¼#¼d¿i¹i»kÈDÕ>PÓ:QÐ9RÐ*SÐUXÐciÓjÓkˆ÷ ä˜GÔ$Ü× Ò ¤×+Õ+Ø×ÑÔ÷ ,Ñ+ñ øô% ô Úðûô  ô =ÜÐ6¸×<Ñ<ûð=ú÷
 ,×+Ð+ús6   ‚E0 Â:A$F ÅF&Å0E?Å>E?ÆF#ÆFÆF#Æ&F7	c               ó   € V ^8„  d   QhRR/# ©r   r   r$   r   )r   s   "r
   r   r   '  s   € ÷ @ñ @¨$ñ @r   c                ó–   € \        V RR4      ;'       g    / p\        VP                  R4      ;'       d    VP                  R4      4      # )a?  A /loop set from a messaging chat carries the gateway's ``route`` (platform + chat_id); its wakeup scanner
(``gateway/run_goals.py::_loop_wakeup_fire_one``) fires those and skips route-less CLI/TUI loops. Mirror it here
so a Desktop viewer of the same session never consumes the tick and strands the reply off the chat.ÚrouteNÚplatformÚchat_id)Úgetattrr$   r   )rë   rú   s   & r
   Ú_loop_route_is_gateway_chatrþ   '  s?   € ô �E˜7 DÓ)×/Ð/¨R€EÜ�—	‘	˜*Ó%×>Ð>¨%¯)©)°IÓ*>Ó?Ð?r   c               ó    € V ^8„  d   QhRRRR/# r�   r   )r   s   "r
   r   r   /  s   € ÷ ñ °ð ¸ñ r   c                ó  € V P                  R4      ;'       g    R;p'       g   R#  ^ RIHp ^ RIHp \        V RR7      ;_uu_ 4        V! VR7      pVP                  4       '       d'   \        VP                  4      '       g    RRR4       R	# V! VR7      pVP                  4       ;'       d    \        W4      '       * uuRRR4       #   + '       g   i     R# ; i  \         d    \        P                  R
TR	R7        R# i ; i)uù  True while THIS process's notification poller is the only driver of an active /loop or /heartbeat for
``session`` â€” the reapers must then keep the detached session (and with it the poller) alive, or the schedule
freezes until a client reattaches. Gateway-routed schedules are fired by the gateway, so they never pin the
session here. Bounded: a loop pauses at its tick budget and a stopped/paused schedule releases the session.
Fail-open to False: an unreadable store must not make a session unreapable.r   r   Frã   )ÚLoopManager)Úhydrate_secretsrå   NTz#wakeup-schedule check failed for %s)Úexc_info)r   ré   rä   Úhermes_cli.loopsr  Ú_session_profile_runtime_scoperê   rþ   rë   rß   r   ÚloggerÚdebug)r   ró   rä   r  r·   rg   s   &     r
   Ú"_session_owns_live_wakeup_scheduler  /  sÌ   € ð —{‘{ =Ó1×7Ð7°RÐ7ˆGÖ7ÙðÝ9Ý0Ü+¨GÀU×KÖKÙ¨'Ô2ˆDØ�~‰~×ÒÔ(CÀDÇJÁJ×(OÒ(OØ÷ LÑKñ )°GÔ<ˆIØ×&Ñ&Ó(×`Ð`Ô1NÈwÓ1`Ô-`÷ L×K×KÓKûô ô Ü�‰Ð:¸GÈdˆÔSÚðúsA   §!C Á<C	ÂC ÂC	Â.C	Â>
C Ã	C	ÃC ÃC Ã#DÄDc               ó    € V ^8„  d   QhRRRR/# r�   r   )r   s   "r
   r   r   E  s   € ÷ Sñ S¸ð SÀñ Sr   c                óp   € V P                  R4      '       d   R# ^ RIHp ^ RIHp V! V\        V 4      4      # )u–  True while a background process this session started will still report back into it (``notify_on_complete``
or ``watch_patterns``): running, or its notice not yet routed (see ``tools.process_registry_awaiting``). The notice
reaches the model only through THIS session's notification poller, and closing the session kills the process
(``agent_close``), so the reapers must keep it alive. Ownership is the set close() kills by â€” the agent's raw
spawning task ids, which keep pre-compression ids after the session key rotates. Bounded by delivery: the session
is released once routing admits the notice's turn (``running`` then protects it), requeues or drops it.r�   F©Úprocess_registry)Úawaits_notification)r   Útools.process_registryr  Útools.process_registry_awaitingr  Ú_session_process_owners)r   r  r  s   &  r
   Ú*_session_owns_pending_process_notificationr  E  s3   € ð ‡{�{Ð+×,Ò,ñ Ý7ÝCÙÐ/Ô1HÈÓ1QÓRÐRr   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   r   r   )r   s   "r
   r   r   U  s   € ÷ jñ j Tð j¨cñ jr   c                óš   € V P                  R4      p0 \        VRR4      m\        V P                  R4      ;'       g    R4      kR0,
          # )z_The raw spawning ids ``close()`` kills by (pre-compression ids included), plus the current key.ÚagentÚ_process_owner_task_idsr   r   r   )r   rý   r   )r   r  s   & r
   r  r  U  sJ   € à�K‰K˜Ó €EØbŒW�UÐ5°rÓ:Ðb¼CÀÇÁÈMÓ@Z×@`Ð@`Ð^`Ó<aÐbÐfhÐeiÕiÐir   c               ó$   € V ^8„  d   QhRRRRRR/# rá   r   )r   s   "r
   r   r   [  s!   € ÷ 8ñ 8 3ð 8°ð 8¸$ñ 8r   c                ó  €  ^ RI HpHp TP	                  R4      ;'       g    R;p'       g   R# T! TR7      pTP                  4       '       d*   T! T4      '       g   \        TP                  4      '       d   R# \        T4      '       g   R# TP                  4       ;p'       g   \        T4       R# R\        \        P                  4       R,          4       2p\        Y4        \        T RTP                  '       d   TP                  P                  MR	 R
24       TP!                  4       P#                  R4      '       d   \%        YpYT4       R# \'        RT 4       \)        YpY4       R#   \         d     R# i ; i  \         d}   p\+        RT4       \        T4       \,        P.                  ! \        4      ;_uu_ 4        TP1                  4        RRR4       M  + '       g   i     M; i\        Y4        Rp?R# Rp?ii ; i)záFire a due /loop wakeup for an idle TUI/Desktop/dashboard session (per-session poller, coarse cadence). Claims
the session (running=True) before dispatching so a racing user prompt wins; the post-turn hook completes the tick.)r  Úgoal_blocks_loop_tickNr   r   rå   Ú__loop__rè   u   â†» /loop wakeup #Ú?ræ   Ú/zmessage.startzloop wakeup dispatch failed)r  r  r  r   r   rì   rþ   rë   r’   Ú	fire_tickr‹   rï   r¦   rÌ   r»   Úticks_firedrÆ   rz   rÔ   r¹   r®   rž   rð   rñ   rË   )	r   r   r  r  ró   rÎ   r½   r«   r•   s	   &&       r
   Ú_maybe_fire_tui_loop_tickr  [  s…  € ðßGð —{‘{ =Ó1×7Ð7°RÐ7ˆGÖ7ÙÙ
 Ô
)€CØ�:‰:�<Š<Ñ0°×9Ò9Ô=XÐY\×YbÑYb×=cÒ=cÙÜ˜W×%Ò%ÙØ—m‘m“oÐ%ˆFÖ%Ü˜GÔ$ÙØ”SœŸ™› tÕ+Ó,Ð-Ð
.€CÜ% cÔ3ð8Ü˜3Ð"4ÈcÏiÏiÈi°S·Y±Y×5JÒ5JÐ]`Ð4aÐakÐ lÔmØ�=‰=‹?×%Ñ% c×*Ò*Ü" 3¨W¸6ÖBä�/ 3Ô'Ü˜s¨Ö9øô) ô Úðûô* ô 8ÜÐ8¸#Ô>Ü˜GÔ$Ü× Ò ¤×+Õ+Ø×ÑÔ÷ ,×+×+Ð+úä)¨#×7Ò7ûð8úsN   ‚E* Ã$AE< ÅE< ÅE< Å*E9Å8E9Å<HÆ9G>Ç GÇ	G>ÇG*Ç%G>Ç>Hc               ó$   € V ^8„  d   QhRRRRRR/# )r   ÚvalueÚAnyÚlimitrï   r   r   r   )r   s   "r
   r   r   }  s!   € ÷ 4ñ 4˜#ð 4 cð 4¨cñ 4r   c                ó‚   € \        V 4      P                  4       P                  4       pV'       d   R V^ ,          RV  2# R# )Ú
Nr   )r   rÊ   Ú
splitlines)r   r"  Úliness   && r
   Ú_kb_first_liner'  }  s=   € Ü�‹J×ÑÓ×)Ñ)Ó+€Eß&+ˆR��a•˜˜%Ð Ð!Ð"Ð3°Ð3r   c               ó$   € V ^8„  d   QhRRRRRR/# ©r   rÑ   r   Útitler   r   r   )r   s   "r
   r   r   ‚  s!   € ÷ )ñ ) ð )¨cð )°cñ )r   c                óº   € VP                  R 4      '       d   \        VR ,          ^È4      M*\        V RR4      '       d   \        V P                  ^ 4      MRpRV V 2# )ÚsummaryrÂ   Nr   u
    done â€” )r   r'  rý   rÂ   )ÚtaskrÑ   r*  Úhandoffs   &&& r
   Ú_kb_completedr/  ‚  sU   € Ø:A¿+¹+Ài×:PÒ:PŒ~˜g iÕ0°#Ô6Ü8?ÀÀhÐPT×8UÒ8U”N 4§;¡;°Ô4Ð[]ð à˜�w˜w˜iÐ(Ð(r   c               ó$   € V ^8„  d   QhRRRRRR/# r)  r   )r   s   "r
   r   r   ˆ  s!   € ÷ 5ñ 5 ð 5¨cð 5°cñ 5r   c                óÞ   € \         P                  ! \        \        4      ;_uu_ 4        R \	        VP                  R4      ;'       g    ^ 4       R2uuRRR4       #   + '       g   i     R# ; i)z timed out (max_runtime=Úlimit_secondszs); will retryNz' timed out (max_runtime=0s); will retry)rð   rñ   Ú	TypeErrorÚ
ValueErrorrï   r   )r-  rÑ   r*  s   &&&r
   Ú_kb_timed_outr5  ˆ  sK   € Ü	×	Ò	œY¬
×	3Õ	3Ø)¬#¨g¯k©k¸/Ó.J×.OÐ.OÈaÓ*PÐ)QÐQ_Ð`÷ 
4×	3×	3Ñ	3á4ús   ¨(AÁA,	u   âœ”u   â�¸c                ó–   € R VP                  R4      '       d+   R\        VP                  R4      4      R,           2,           # R,           # )z blockedÚreasonr˜   :Né    Nr   ©r   r   ©ÚtÚpr*  s   &&&r
   r5   r5   ‘  s<   € ¨:Ð^_×^cÑ^cÐdl×^mÒ^m¸2¼cÀ!Ç%Á%ÈÃ/Ó>RÐSWÕ>XÐ=YÐ9ZÖ+vÐsuÖ+vr   u   âœ–c                ó–   € R VP                  R4      '       d+   R\        VP                  R4      4      R,           2,           # R,           # )z& gave up after repeated spawn failuresÚerrorr$  :NéÈ   Nr   r9  r:  s   &&&r
   r5   r5   ’  s=   € Ð+SØ78·u±u¸W·~²~�Rœ˜AŸE™E '›NÓ+¨DÕ1Ð2Ð3ö,OØKMö,Or   c                ó   € R # )z1 worker crashed (pid gone); dispatcher will retryr   r:  s   &&&r
   r5   r5   ”  s   € Ñ+^r   u   â�±u   ðŸ”„c                ó>   € R VP                  R4      ;'       g    R 2# )u    â†’ r„   r   rE   r:  s   &&&r
   r5   r5   –  s   € ¨U°1·5±5¸³?×3HÐ3HÀbÐ2IÑ+Jr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úsubr   Ú
board_slugr   r   zOptional[str]r   )r   s   "r
   r   r   š  s&   € ÷ 
]ñ 
] 4ð 
]¸sð 
]À}ñ 
]r   c                óŽ  € \         P                  \        VRR4      4      ;pf   R# Vw  rVV P                  RR4      p\        VRR4      ;'       g    TR,          p\        VRR4      ;'       g    Rp	V R2V'       d   R	V R
2MR,           V	'       d   RV	 R2MR,           p
T
 RT T! T\        VRR4      ;'       g    / V4       2# )z–Single-line notification text for one kanban event; wording mirrors gateway/kanban_watchers.py (reads the same
as on Telegram). None for silent kinds.r¶   r   NÚtask_idr*  :Néx   NÚassigneeÚ Ú[z] Ú@zKanban rÑ   )Ú_KANBAN_EVENT_FORMATTERSr   rý   )rC  r-  ÚevrD  rÞ   ÚglyphÚfmtrF  r*  ÚwhoÚprefixs   &&&&       r
   Ú_format_kanban_event_textrR  š  sÑ   € ô *×-Ñ-¬g°b¸&À"Ó.EÓFÐFˆÒOÙØ�J€EØ�g‰g�i Ó$€GÜ�T˜7 DÓ)×4Ð4¨W°dÕ;€EÜ
�$˜
 DÓ
)×
/Ð
/¨R€CØˆw�aˆ[·*˜a 
˜|¨2Ñ.À"ÕE×WZÈ1ÈSÈEÐQRÉÐ`bÕc€FØˆX�W˜W˜I¡c¨$´¸¸IÀtÓ0L×0RÐ0RÐPRÐTYÓ&ZÐ%[Ð\Ð\r   c               ó   € V ^8„  d   QhRR/# )r   r   ztuple[str, str]r   )r   s   "r
   r   r   §  s   € ÷ $ñ $ oñ $r   c                ó„  € T;'       g    / P                  R4      ;'       g    V P                  pT;'       g    / P                  R4      p T\        V'       d-   \        V4      P	                  4       P                  4       4      3# V P                  V4      P                  4       4      3#   \         d    TRT 23u # i ; i)ub   (slug, resolved DB identity) â€” multiple slugs can point at one DB when HERMES_KANBAN_DB pins it.ÚslugÚdb_pathzslug:)r   ÚDEFAULT_BOARDr   ÚPathÚ
expanduserÚresolveÚkanban_db_pathr   )Ú_kbÚ
board_metarU  rV  s   &&  r
   Ú_kb_board_keyr^  §  s­   € à×Ð˜"×!Ñ! &Ó)×>Ð>¨S×->Ñ->€DØ×Ð˜R×$Ñ$ YÓ/€Gð$Ø”SÇœ˜g›×1Ñ1Ó3×;Ñ;Ó=ÓqÐqÐqÈc×N`ÑN`ÐaeÓNf×NnÑNnÓNpÓqÐqÐqøÜô $Ø�u˜T˜F�^Ð#Ò#ð$ús   Á9B* Â#B* Â*B?Â>B?c               ó$   € V ^8„  d   QhRRRRRR/# )r   rU  r   r   r   Úlistr   )r   s   "r
   r   r   ±  s!   € ÷ 'ñ '˜cð '°ð '¸ñ 'r   c                ó0  € ^ RI Hp ^ RI Hp \        P                  ! \
        4      ;_uu_ 4        VP                  VRVR7      ^ 8X  d   . uuRRR4       #  RRR4        VP                  VR7      p. p\        P                  ! T4      ;_uu_ 4         TP                  T4      pT EFv  pTP                  R4      ;'       g    RP                  4       R8w  g   TP                  R	4      T8w  d   KJ  \        TR
,          TR,          TR	,          TP                  R4      ;'       g    RR7      p	TP                  ! T3R\        /T	B w  r«pT'       g   K­  T P                  YXR
,          4      p^ RIHp ^ RIHp T FA  p\)        Y�TT4      pT'       g   K  TP+                  T! T4      '       d	   T! T4      MT4       KC  	  T'       g   EK#  \-        TRR4      R8X  g   EK8  \        P                  ! \
        4      ;_uu_ 4        TP.                  ! T3/ T	B  RRR4       EKy  	  RRR4       T#   + '       g   i     ELÞ; i  \
         d    . u # i ; i  \
         d    . u uuRRR4       # i ; i  + '       g   i     EKÛ  ; i  + '       g   i     T# ; i)u  Claim + format this session's unseen events on one board. One poller per live session: the board is not opened
writable unless it has a subscription owned by this exact session (a failed read-only probe â€” locked/corrupt DB â€”
falls through so delivery is preserved).)Úkanban_db_connect)Úkanban_db_notifyÚtui)Úboardrû   rü   N)re  rû   r   rü   rF  Ú	thread_id)rF  rû   rü   rf  Úkinds)Údiagnostic_event)ÚDiagnosticTextr„   Úarchived)Ú
hermes_clirb  rc  rð   rñ   r   Úcount_notify_subsÚconnectÚclosingÚlist_notify_subsr   Úlowerr   Úclaim_unseen_events_for_subÚ_KANBAN_NOTIFY_KINDSÚget_taskÚ gateway.kanban_watchers_notifierrh  Úgateway.warning_notificationsri  rR  Úappendrý   Úremove_notify_sub)r\  rU  r   Ú_kbcÚ_kbnÚconnÚtextsÚsubsrC  Ú	sub_identÚ_oldÚ_newÚeventsr-  rh  ri  rM  r¬   s   &&&               r
   Ú_kb_poll_boardr�  ±  s&  € õ 5Ý3Ü	×	Ò	œY×	'Õ	'Ø×!Ñ!¨°uÀkÐ!ÓRÐVWÔWØ÷ 
(Ò	'ØW÷ 
(ðØ�|‰| $ˆ|Ó'ˆð €EÜ	×	Ò	˜D×	!Õ	!ð	Ø×(Ñ(¨Ó.ˆDô ˆCØ—‘˜
Ó#×)Ð) r×0Ñ0Ó2°eÔ;¸s¿w¹wÀyÓ?QÐU`Ô?`ÙÜ S¨¥^¸cÀ*½oÐWZÐ[dÕWeØ'*§w¡w¨{Ó';×'AÐ'A¸rôCˆIà!%×!AÒ!AÀ$Ñ!pÔNbÐ!pÐfoÑ!pÑˆD˜ßÙØ—<‘< ¨)¥nÓ5ˆDÝIÝDÛ�Ü0°¸BÀÓE�ß‘4Ø—L‘LÑ9IÈ"×9MÒ9M¡°Ô!5ÐSWÖXñ ÷ Štœ  h°Ó3°z×AÜ×(Ò(¬×3Õ3Ø×*Ò*¨4Ñ=°9Ò=÷ 4Ò3ñ% ÷ 
"ð2 €L÷C 
(×	'Ð	'ûô
 ô ØŠ	ðûô ô 	Ø‰I÷	 
"Ò	!ð	ú÷( 4×3Ñ3ú÷/ 
"Ö	!ð2 €Lús‹   ¯H+ÁH? ÂJÂIÂ$JÃA"JÄ%A)JÆJÆ,JÇ	JÇ"JÈ I/ÈJÈ+H<	È?IÉIÉI,ÉJÉ+I,É,JÉ/JÉ:
JÊJ	c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   r`  r   )r   s   "r
   r   r   Û  s   € ÷ [ñ [¨4ð [°Dñ [r   c           	     ó2  a€ \        V P                  R4      ;'       g    R4      pV'       d   V P                  R4      '       d   . #  ^ RIHo  SP                  RR7      p/ pT3R lT 4        F  w  rETP                  YT4       K  	  TP                  4        UUu. uF  p\        SYA4       F  qfNK  	  K  	  upp#   \         d    . u # i ; i  \         d6     SP                  SP                  4      .p L™  \         d    . u u # i ; ii ; iu uppi )aZ  Claim unseen terminal kanban events for this session's ``platform="tui"`` subscriptions (``kanban_create``
auto-subscribes with ``chat_id=HERMES_SESSION_KEY``; no "tui" messaging adapter exists, so this poller is the
delivery path). Same atomic cursor-claim as the gateway notifier: exactly-once even if a gateway polls the same DB.

See #59890.
r   r   r.   )Ú	kanban_dbF)Úinclude_archivedc              3  ó<   <"  € T F  p\        SV4      x € K  	  R # 5irV   )r^  )r/   r]  r\  s   & €r
   r0   Ú0_collect_kanban_notifications.<locals>.<genexpr>ò  s   øé € ÐSÉF¸jœ=¨¨j×9Ð9ËFùs   ƒ)r   r   rk  r„  r   Úlist_boardsÚread_board_metadatarW  Ú
setdefaultr3   r�  )r   r   ÚboardsÚuniquerU  Úresolvedr;  r\  s   &      @r
   Ú_collect_kanban_notificationsrŽ  Û  s  ø€ ô �g—k‘k -Ó0×6Ð6°BÓ7€Kß˜'Ÿ+™+ l×3Ò3Øˆ	ðÝ/ðØ—‘°%�Ó8ˆð €FÜSÉFÖS‰ˆØ×Ñ˜(Ö)ñ Tà Ÿ-™-œ/ÔZ™/�$´>À#ÀtÖ3Y¨aŠAÑ3Y‰A™/ÒZÐZøô ô ØŠ	ðûô ô ð	Ø×-Ñ-¨c×.?Ñ.?Ó@ÐAŠFøÜô 	ØŒIð	úðüó [sB   ÁB= ÁC ÂDÂ=CÃCÃDÃC:Ã:DÄDÄDÄDc               ó$   € V ^8„  d   QhRRRRRR/# rá   r   )r   s   "r
   r   r   ÷  s!   € ÷ 0ñ 0˜Cð 0¨$ð 0°4ñ 0r   c                ó|   € \        V4      ;_uu_ 4        \        W4       R R R 4       R #   + '       g   i     R # ; irV   )r  Ú_notif_poll_kanban_scopedr    s   &&r
   Ú_notif_poll_kanbanr’  ÷  s$   € Ü	'¨×	0Õ	0Ü! #Ô/÷ 
1×	0×	0Ò	0ús   ”*ª;	c               ó$   € V ^8„  d   QhRRRRRR/# rá   r   )r   s   "r
   r   r   ü  s&   € ÷ oñ o 3ð o°ð o¸$ñ or   c           
     óJ  a a
€  \        V4      pV F%  o
^ RIHpHp V! V V
3R lR\        S
V4      R7       K'  	  V'       d"   VP                  R. 4      P                  V4       VP                  R4      '       d   \        V4      '       g   R# VR,          ;_uu_ 4        VP                  R4      ;'       g    . p^ R	IHpHp V! R4      '       * pT;'       d    \        V^ ,          V4      p	V U
u. uF  q¨'       d   \        W¤4      V	8X  g   K  V
NK   	  pp
V U
u. uF   q¨'       g   K  \        W¤4      V	8w  g   K  V
NK"  	  up
VR&   RRR4       \        P                  ! \        4      ;_uu_ 4        \        R
\        \         P!                  4       R,          4       2S VRP#                  X4      R3/ X	'       d   RRR//M/ B  RRR4       R#   \         d   p\        RT4       . p Rp?ELÝRp?ii ; iu up
i u up
i   + '       g   i     LÀ; i  + '       g   i     R# ; i)zÇOne kanban poll: emit new texts, buffer them, and run the buffered batch as a turn if idle. Events are
cursor-claimed (never re-queued), so they wait in the buffer instead of dropping the agent turn.zkanban notification poll failedN)ri  Úrender_notificationc                 ó&   <€ \        R S RRRS/4      # ©rµ   r¶   Úprocessr¬   r¸   rº   s   €€r
   r5   Ú+_notif_poll_kanban_scoped.<locals>.<lambda>  s   ø€ ¤E¨/¸3ÀÈÐTZÐ\`Ð@aÔ$br   rd  ©rû   Ú
diagnosticÚ_kanban_pendingr‰   )ri  Úwarning_notifications_enabledÚ	__notif__rè   r$  z#kanban notification dispatch failedÚdisplay_metadataÚnotification_categoryr›  )rŽ  r   rž   ru  ri  r•  Ú
isinstancerŠ  Úextendr   r’   r�  rð   rñ   r²   rï   r¦   Újoin)r   r   r{  r•   ri  r•  Úpendingr�  rÇ   r›  r¬   Úbatchs   f&        ` r
   r‘  r‘  ü  sÄ  ù€ ðÜ-¨gÓ6ˆó ˆßUÙÕbØ%*´zÀ$ÈÓ7W÷	Yñ ÷ Ø×ÑÐ,¨bÓ1×8Ñ8¸Ô?Ø�;‰;Ð(×)Ò)Ô1BÀ7×1KÒ1KÙØ	�×	 ×	 Ø—+‘+Ð/Ó0×6Ð6°Bˆß_Ù1°%Ó8Ô8ˆØ×EÐEœz¨'°!­*°nÓEˆ
Ù")Ói¡'˜$¶¼*ÀTÓ:ZÐ^hÑ:h—�¡'ˆÐiÙ7>Ó%{±w¨tÃ%¤dÌJÐW[ÓLlÐpzÑLz§d d±wÑ%{ˆÐ!Ñ"÷ 
!ô 
×	Ò	œY×	'Õ	'Ü˜	¤#¤d§i¡i£k°DÕ&8Ó"9Ð!:Ð;¸SÀ'È4Ï9É9ÐUZÓK[Ø;ñ	oçZdÐ,Ð/FÈÐ.UÑVÐjlò	o÷ 
(Ñ	'øô% ô ÜÐ<¸cÔBØŽûðüò  jùÚ%{÷ 
!×	 ú÷ 
(×	'Ð	'úsf   „G Â9G>ÃG>Ã0G4ÄG4ÄG>Ä	G9Ä(G9Ä:G9Å G>Å0AHÇG1ÇG,Ç,G1Ç4
G>Ç>H	ÈH"	c                óš   € ^ RI Hp ^ RIHp V'       d   V! V R,          V4       T;'       g    VP                  P
                  ! V 4       R# )é    )Údefer_completion_deliveryr  rs   N)Útools.async_delegationr¨  r  r  Úcompletion_queueÚput)rA   Úclaimr«  r¨  r  s   &&&  r
   Ú_notif_defer_eventr­    s:   € Ý@Ý7ßÙ! # oÕ"6¸Ô>Ø×1Ð1Ð×-Ñ-×1Ñ1Ð1°3Ö7r   c               ó    € V ^8„  d   QhRRRR/# r�   r   )r   s   "r
   r   r   !  s   € ÷ Cñ C¨4ð C°Dñ Cr   c                óD  € \        V 4      ;_uu_ 4        \        4       P                  R4      ;'       g    / P                  R4      pRRR4       XRJ ;'       g5    \        T;'       g    R4      P	                  4       P                  4       R8H  #   + '       g   i     LP; i)zóWhether the owning profile set ``display.background_process_notifications: off``. Same
gate the messaging gateway applies to its process-event injection; only ``off`` matters
here (the other modes shape gateway chat receipts, not agent wakes).ÚdisplayÚ background_process_notificationsNFr   Úoff)r  Ú	_load_cfgr   r   rÊ   rp  )r   Úraws   & r
   Ú_background_notifications_offrµ  !  st   € ô 
(¨×	0Õ	0Ü‹{�‰˜yÓ)×/Ð/¨R×4Ñ4Ð5WÓXˆ÷ 
1à�%ˆ<×BÐBœ3˜sŸy˜y b›>×/Ñ/Ó1×7Ñ7Ó9¸UÑBÐB÷ 
1×	0ús   ”3BÂB	c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   r   r   r   r   rA   r¬   r   r‡   r   )r   s   "r
   r   r   *  s/   € ÷ $(ñ $(˜sð $(¨Tð $(¸ð $(ÀCð $(ÈDñ $(r   c                óT  € ^ RI HpHpHp  V! VR4      pVf   \        V4       R# VP                  R4      p	/ p
V	R8X  d   RRR	\        V4      /p
MV	R
8X  d   ^ RI	H
p RV/p
^ RIHp V! V4      '       d   RV
P                  R	/ 4      R&    \        R\        \         P!                  4       R,          4       2WVR3RR/V
B '       g   \#        W'4       \%        V4       R#  T! Y'4       R#   \         d   p\        RT4       Rp Rp?LóRp?ii ; i  \         d    T! Y'4        R# i ; i)zERun the claimed (running=True) agent turn for one notification event.©Úclaim_event_deliveryÚcomplete_event_deliveryÚrelease_event_deliveryz
tui-pollerz"notification delivery claim failedNr\   r]   Údisplay_kindÚasync_delegation_completerŸ  rg   )ÚHEARTBEAT_DISPLAY_KIND©Údiagnostic_process_eventr›  r   rž  rè   z#notification poller dispatch failedÚreport_ownership_refusalF)r©  r¹  rº  r»  r   rž   r‹   r   Ú"_async_delegation_display_metadataÚ$tools.process_registry_notificationsr¾  Úagent.notification_presentationrÀ  rŠ  r²   rï   r¦   r­  r©   )r   r   rA   r¬   r¹  rº  r»  r¬  r•   r{   r°   r¾  rÀ  s   &&&&         r
   Ú_notif_dispatch_eventrÅ  *  sG  € çlÑlðÙ$ S¨,Ó7ˆð ‚}ô 	˜GÔ$ÙØ�w‰w�v‹€HØ€FØÐ%Ô%Ø Ð"=Ð?QÔSuÐvyÓSzÐ{‰Ø	�[Ô	 õ 	PØ Ð"8Ð9ˆÝHÙ ×$Ò$ØMYˆ×ÑÐ,¨bÓ1Ð2IÑJðÜ˜y¬¬T¯Y©Y«[¸4Õ-?Ó)@Ð(AÐBÀCÐRVØBñnØ]bðnØfl÷nð nä˜sÔ*Ü" 7Ô+Ùð	nñ ˜CÖ'øô? ô ÜÐ?ÀÔEØ�ûðûô8 ô Ù˜sÔ*Úðús*   Œ	C* ÂAD Ã*DÃ5DÄDÄD'Ä&D'ÚownedFc               ó   € V ^8„  d   QhRR/# rø   r   )r   s   "r
   r   r   Q  s   € ÷ ?ñ ?Ðrvñ ?r   c               óÎ  a a€ VP                   p	VP                  RR4      VP                  R4      R8H  rºV'       gR   \        S W4      '       d@   Ve   VP                  V4       R# V	P	                  V4       \
        P                  R4       R# V'       Eg   \        V4      '       Ed   \        S W4      '       gõ   \        VP                  R4      ;'       g    R4      \        VP                  R4      ;'       g    R4      rÜVfv   T;'       d    \        VP                  R	4      4      pV'       d   V'       g   \        P                  M\        P                  ! R
W¬VS 4       V'       d   ^ RIHp V! V4       R# V'       d   VP                  V4       R# \        P                  RW¬V4       R# V
R8X  d*   VP!                  VP                  RR4      4      '       d   R# V! V4      pV'       g   R# \#        V4      pVV9  d^   ^ RIHpHp V'       d	   V! V4      MV
R8X  d
   V! V.4      MTo^ RIHp ^ RIHp V! VV 3R lRV! V4      R7       VP3                  V4       V
R8w  d   \5        V4      '       d   R# V
R8X  d   Ve   VP                  VV34       R# \7        V4      '       g/   V	P	                  V4       Ve   R# \
        P                  R4       R# \9        S WV4       R# )u5  Route one dequeued event: foreign (another live session owns it) â†’ requeued, or onto ``deferred`` during the
shutdown drain; unowned (addressed but unprovable â€” never adopt an orphan) â†’ dropped, except delegation payloads
deferred for a resume; ours (or ownerless legacy, kept process-global) â†’ status.update once, then an agent turn if
idle. False = the drain must stop (session busy). ``owned`` skips the ownership gates for events a caller already
drained through ``_session_owns_notification_event`` (the post-turn safety net), so lineage resolves once.r\   rm   r]   gš™™™™™¹?TrC   r   r   ÚrestoredzWDropping unowned %s notification (origin=%r key=%r) instead of delivering to session %s)Úreturn_completion_offerzIDropping unowned %s notification during shutdown drain (origin=%r key=%r)ro   )Úasync_delegation_display_textÚprocess_completion_display_textr¿  )r•  c                 ó&   <€ \        R SRRRS /4      # r—  r¸   )Údisplay_textr   s   €€r
   r5   Ú%_notif_handle_event.<locals>.<lambda>  s   ø€ ¤E¨/¸3ÀÈÐTZÐ\hÐ@iÔ$jr   rd  rš  FrŸ   )rª  r   rK   rv  r«  r¦   r§   re   rW   r   r$   r  Úwarningr  r©  rÊ  Úis_completion_consumedr~   rÃ  rË  rÌ  rÄ  rÀ  ru  r•  Úaddrµ  r’   rÅ  )r   r   rA   ÚemittedÚregistryrO  ÚdeferredÚcompletionsrÆ  Úqueuer{   Úis_delegationr×   ÚkeyrÉ  rÊ  r¬   Ú	dedup_keyrË  rÌ  rÀ  r•  rÎ  s   f&&&&&&&$             @r
   Ú_notif_handle_eventrÛ  Q  sd  ù€ ð ×%Ñ%€EØ!Ÿg™g f¨lÓ;¸S¿W¹WÀV»_ÐPbÑ=bˆmßÔ:¸3À×MÒMØÒØ�O‰O˜CÔ ñ ð �I‰I�cŒNÜ�J‰J�sŒOÙßˆ5Ô7¸×<Ó<ÔEeÐfiÐkr×ExÒExÜ˜#Ÿ'™'Ð"8Ó9×?Ð?¸RÓ@Ä#ÀcÇgÁgÈmÓF\×FbÐFbÐ`bÓBc�ØÒð %×BÐB¬¨c¯g©g°jÓ.AÓ)BˆHß,·XŒV�^Š^Ä6Ç<Á<ÐOØiØ # sô,÷ ÝJÙ'¨Ô,ñ
 ÷	 Ø�O‰O˜CÔ ñ ô �L‰LÐdÐfnÐx{Ô|ÙØ�<Ô H×$CÑ$CÀCÇGÁGÈLÐZ\ÓD]×$^Ò$^ÙÙˆs‹8€DßÙô .¨cÓ2€IØ˜Ôßwß>KÑ5°cÔ:ØGOÐS_ÔG_Ñ<¸c¸UÔCÐeið 	åLÝEÙÕjØ%*Ñ7OÐPSÓ7Tõ	Và�‰�IÔØÐ%Ô%Ô*GÈ×*PÒ*Pñ Ø�<Ô KÒ$;Ø×Ñ˜C ˜;Ô'ÙÜ˜W×%Ò%Ø�	‰	�#ŒØÒÙÜ�
‰
�4ÔÙÜ˜#˜w¨TÔ2Ùr   c                óD  € ^ RI HpHp ^ RIHpHpHp	 V'       g   R# \        V4      '       gS   V F1  w  r«Ve   VP                  MVP                  P                  ! V
4       K3  	  Vf   \        P                  R4       R# . p V F'  w  r­V! V
R4      ;pf   K  VP                  W­V34       K)  	  T! \        ;QJ d    . R V 4       F  NK  	  5M! R V 4       4      4      pVP                  V4      pTf   \#        T4        Teœ   \%        R\'        \        P                  4       R	,          4       2YTR
TRRTP)                  T4      /R7      '       gN   T F6  w  r«p\+        Y®Te   TP                  MTP                  P                  4       K8  	  Tf   \-        T4       R# T F  w  r«pT! Y®4       K  	  R#   \         d7   p\!        RT4       \#        T4       T F  w  r«pT	! Y®4       K  	   Rp?R# Rp?ii ; i  \         d    T F  w  r«pT	! Y®4       K  	   R# i ; i)r§  )ÚPROCESS_COMPLETE_DISPLAY_KINDÚProcessNotificationBatchr¸  NrŸ   ztui-completion-batchc              3  ó.   "  € T F  w  rq1V3x € K  	  R # 5irV   r   )r/   ÚeventÚ
event_textÚ_claims   &   r
   r0   Ú._notif_dispatch_completions.<locals>.<genexpr>¤  s   é € Ð.lÑdkÑG`ÀuÐZ`°zÕ/BÓdkùs   ‚z#completion batch preparation failedrž  rè   z completion batch dispatch failedFrÎ  )r¼  rÁ  rŸ  )rÃ  rÝ  rÞ  r©  r¹  rº  r»  r’   rv  rª  r«  r¦   r§   rk   Úrenderr   rž   r‹   r²   rï   rÎ  r­  r©   )r   r   ÚnotificationsrÔ  rÕ  rÝ  rÞ  r¹  rº  r»  rà  Ú_textÚclaimedrá  r¬  r¥  r¬   r•   s   &&&&&             r
   Ú_notif_dispatch_completionsrè  “  s   € ßlßlÑlçÙÜ˜W×%Ò%Û)‰LˆEØ (Ò 4ˆX�_Š_¸(×:SÑ:S×:WÑ:WÐWÐY^Ö_ñ *àÒÜ�J‰J�tÔÙØ€GðÛ!.ÑˆEÙ-¨eÐ5KÓLÐL�ÔYØ—‘ °5Ð9Ö:ñ "/ñ )¯¬Ñ.lÑdkÓ.l¯©Ñ.lÑdkÓ.lÓ)lÓmˆØ�|‰|˜HÓ%ˆð ‚|Ü˜GÔ$ðØÒÜ  9¬S´·±³¸tÕ1CÓ-DÐ,EÐ!FÈÐVZØ!CÐRoØ:?Ø3AÀ5×CUÑCUÐV^ÓC_Ð2`÷bó bó ,3Ñ'�E %Ü& uØ+3Ò+?˜ŸšÀX×E^ÑE^×EbÑEbödñ ,3ð Ò#Ü*¨7Ô3Ùó
  'Ñˆ�eÙ Ö-ó  'øô1 ô ÜÐ@À#ÔFÜ˜GÔ$Û#*ÑˆE˜%Ù" 5Ö0ñ $+åûðûô( ô Û#*ÑˆE˜%Ù" 5Ö0ñ $+âðús7   ÂF8 Â#F8 Â=6F8 ÄBG< Æ8G9Ç+G4Ç4G9Ç<HÈHc               óD  € . p\        V4       F�  w  ršV
P                  RR4      R8w  d   \        WW„V4       . p\        WW£WEWhVR7	      '       d   KC  W)^,           R  F/  pVe   VP                  MVP
                  P                  ! V4       K1  	   M	  \        WW„V4       R# )zUOne ready snapshot: ownership and UI emission per event, one turn per completion run.r\   rm   )rÆ  N)Ú	enumerater   rè  rÛ  rv  rª  r«  )r   r   r€  rÓ  rÔ  rO  rÕ  rÆ  rÖ  Úindexrà  Ú	remainings   &&&&&&&$    r
   Ú_notif_handle_readyrí  Â  s˜   € à€KÜ! &Ö)‰ˆØ�9‰9�V˜\Ó*¨lÔ:Ü'¨°kÈXÔVØˆKÜ" 3°ÀÐPXÐmr×sÕsØ#¨A¥I JÓ/�	Ø$,Ò$8�—’¸h×>WÑ>W×>[Ñ>[Ð[Ð]fÖgñ 0áñ *ô   ¨kÀXÖNr   c               ó(   € V ^8„  d   QhRRRRRRRR/# ©	r   Ú
stop_eventúthreading.Eventr   r   r   r   r   r‡   r   )r   s   "r
   r   r   Ð  s/   € ÷ Cñ C¨/ð CÀð CÈdð CÐW[ñ Cr   c                ó~   € \        V4      ;_uu_ 4        \        WV4       R R R 4       R #   + '       g   i     R # ; irV   )r  Ú _notification_poller_scoped_loop)rð  r   r   s   &&&r
   Ú_notification_poller_looprô  Ð  s&   € Ü	'¨×	0Õ	0Ü(¨¸'ÔB÷ 
1×	0×	0Ò	0ús   ”+«<	c               ó(   € V ^8„  d   QhRRRRRRRR/# rï  r   )r   s   "r
   r   r   Õ  s*   € ÷ 9!ñ 9!°ð 9!Àsð 9!ÐUYð 9!Ð^bñ 9!r   c                ó   aaaaa€ ^ RI Hp ^ RIHo ^ RIHpHp ^ RIHo SP                  4        SP                  pSP                  R\        4       4      oVVVVV3R lpR;r‰V P                  4       '       g¹   SP                  R4      '       g¢   \        P!                  4       p
VP#                  V4       W©,
          \$        8¼  d&   T
p	R	\&        3R
\(        33 F  w  r¼ V! SS4       K  	  W¨,
          \.        8¼  d   T
p\1        SS4       V! VR4      pV'       g   Kº   V! VR4       V! V4       KÎ  . pV! V^ 4      p V! VV4       V F  pVP3                  V4       K  	  V! V4       R#   \*         d   p\-        T R2T4        Rp?K²  Rp?ii ; i  \*         d   p\-        RT4        Rp?L‡Rp?ii ; i  T! T4       i ; i  T! T4       i ; i)u  Daemon thread (started by _init_session()) that drains the process-global completion_queue for this session
(ownership routing: _notif_handle_event) and polls ``kanban_notify_subs`` every ``_KANBAN_POLL_SECONDS`` â€” the
delivery path for platform="tui" rows.

Also polls ``kanban_notify_subs`` every ``_KANBAN_POLL_SECONDS`` for this session's TUI kanban
subscriptions and delivers terminal task events the same way (status.update + agent turn) â€” the delivery
path tools/kanban_tools.py documents for platform="tui" rows (issue #59890).
)r]   r  )ÚreleaseÚ
take_ready)Úformat_process_notificationÚ_notification_emittedc           	     ó&   <€ \        SSV SSSV4      # rV   )rí  )r€  rÕ  rÓ  rù  r  r   r   s   &&€€€€€r
   r5   Ú2_notification_poller_scoped_loop.<locals>.<lambda>å  s   ø€ Ô&9ØˆW�f˜gÐ'7Ð9TÐV^ô'`r   g        r.   zloop wakeuprg   z poll failedNg      à?znotification dispatch failed)Útoolsr]   r  r  r  r÷  rø  rÃ  rù  Úrestore_completionsrª  rŠ  r   Úis_setr   r¦   Ú	monotonicÚ maybe_sweep_orphaned_completionsÚ_LOOP_POLL_SECONDSr  rö   r   rž   Ú_KANBAN_POLL_SECONDSr’  r«  )rð  r   r   r]   Úrelease_in_flightrø  r×  ÚhandleÚlast_kanban_pollÚlast_loop_pollÚnowr”   ÚfireÚtick_excÚreadyr•   rÕ  rA   rÓ  rù  r  s   &ff               @@@r
   ró  ró  Õ  s¹  ü€ õ 'Ý7ßXÝPØ×(Ñ(Ô*Ø×-Ñ-€EØ× Ñ Ð!8¼#»%Ó@€G÷`ð `€Fà(+Ð+ÐØ×Ñ×!Ò!¨'¯+©+°l×*CÒ*CÜ�n‰nÓˆà×9Ñ9¸%Ô@ð ÕÔ#5Ô5Ø ˆNØ -Ô/HÐIÈKÔYwÐKxÓy‘
�ðHÙ˜˜gÖ&ñ zð
 Õ!Ô%9Ô9Ø"ÐÜ˜s GÔ,ñ ˜5 #Ó&ˆßÙð	%Ù�5˜$Ôñ ˜eÖ$ð €HÙ�u˜aÓ €Eð!Ùˆu�hÔÛˆCØ�I‰I�cŽNñ ñ 	˜%Ö øô7 !ô HÜ&¨$¨¨|Ð'<¸h×GÒGûðHûô ô 	Dô Ð=¸s×CÑCûð	Dûñ
 ˜eÕ$ûñ 	˜%Õ úsN   Ã	E*Ä	F Ä=#G Å*FÅ5F
Æ
FÆF3ÆF.Æ)F6 Æ.F3Æ3F6 Æ6
G Ç
Gc               ó    € V ^8„  d   QhRRRR/# )r   rA   r   r   r   )r   s   "r
   r   r     s   € ÷ ^ñ ^¨Dð ^°Tñ ^r   c           
     óR  € ^ RI Hp V P                  R4      p\        V\        4      '       d+   V Uu. uF  p\        V\
        4      '       g   K  VNK  	  upM. p\        V4      ;'       g    ^p\        R V 4       4      p\        R V 4       4      pV P                  R4      ;'       g    V P                  R4      pRV! V 4      R\        V P                  R4      ;'       g    R	4      R
TRT;'       g	    WW,
          RV/\        V\        \        34      '       d   RV/C# / C# u upi )zEBuild display-only metadata before the completion event is formatted.)rË  rq   c              3  óT   "  € T F  qP                  R 4      R9   g   K  ^x € K   	  R# 5i)r„   N>   Úsuccessr   rE   ©r/   Úrs   & r
   r0   Ú5_async_delegation_display_metadata.<locals>.<genexpr>  s    é € Ð\¡W ·±°h³ÐC[Ñ0[Ÿ!š!£Wùó   ‚(ž
(c              3  óT   "  € T F  qP                  R 4      R9   g   K  ^x € K   	  R# 5i)r„   N>   r>  ÚfailedrE   r  s   & r
   r0   r    s    é € ÐT¡'˜Q¯U©U°8«_Ð@SÑ-S—q’q£'ùr  Útotal_duration_secondsÚduration_secondsrÎ  rs   r   Ú
task_countÚcompleted_countÚfailed_count)rÃ  rË  r   r¡  r`  r   rÉ   Úsumr   rï   Úfloat)	rA   rË  Úraw_resultsr  rq   r  r  r  Údurations	   &        r
   rÂ  rÂ    s  € åRØ—'‘'˜)Ó$€KÜMWÐXcÔei×MjÒMj¡kÓI¡k ´ZÀÄ4×5HŸ1˜1¡kÒIÐpr€GÜ�W“×"Ð" €JÜÑ\¡WÓ\Ó\€OÜÑT¡'ÓTÓT€LØ�w‰wÐ/Ó0×OÐO°C·G±GÐ<NÓ4O€HØÑ9¸#Ó>ØœS §¡¨Ó!9×!?Ð!?¸RÓ@À,ÐPZØ˜×KÐK°*Õ2KÈ^Ð]ið^ô 2<¸HÄsÌEÀl×1SÒ1SÐ" HÐ-ð^ð ^ð Z\ð^ð ^ùò Js   ²D$ÁD$c               ó   € V ^8„  d   QhRR/# ©r   r   r‡   r   )r   s   "r
   r   r   #  s   € ÷ %ñ %˜Tñ %r   c                 óV  a€ ^ RI Hp  R R lo\        V RR4      f   V3R lV n        \        V RR4      f   V3R lV n        \
        '       gH   \        P                  ! \        4      ;_uu_ 4        ^ R	I	H
p VP                  R
 4       RsRRR4       R# R#   + '       g   i     R# ; i)a,  Idempotently wire process-registry and desktop-tool sinks to renderer events: `agent.terminal.output` and
`terminal.close` (drops a tab without killing the process) route to the window owning the process; desktop-only
tools pass the turn's ``HERMES_UI_SESSION_ID`` as ``sid``. `_emit` is thread-safe.r  c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r
   r   Ú)_wire_desktop_sinks.<locals>.__annotate__*  s   € ÷ uñ u˜sñ ur   c                ó  a€ V e!   \        \        V RR4      ;'       g    R4      MRoS'       g   R# \        ;_uu_ 4        \        V3R l\        P                  4        4       R4      uuR R R 4       #   + '       g   i     R # ; i)Nr   r   c              3  ó‚   <"  € T F4  w  r\        VP                  R 4      ;'       g    R4      S8X  g   K0  Vx € K6  	  R# 5i)r   r   N)r   r   )r/   r   r#   r   s   &  €r
   r0   Ú:_wire_desktop_sinks.<locals>._owner_sid.<locals>.<genexpr>0  s6   øé € ÐoÑ+<¡ ÄÀAÇEÁEÈ-ÓDX×D^ÐD^Ð\^Ó@_ÐcnÑ@nŸšÓ+<ùs   ƒ#?§	?µ
?)r   rý   r   Únextr   rP   )r   r   s   &@r
   Ú
_owner_sidÚ'_wire_desktop_sinks.<locals>._owner_sid*  sU   ø€ àHOÒH[”cœ' '¨=¸"Ó=×CÐCÀÔDÐacˆßÙßŽ^ÜÔo¬9¯?©?Ô+<ÓoÐqsÓt÷ �^�^‹^ús   Á (A3Á3B	Ú	on_outputNc                óF   <€ \        R S! V 4      RV P                  RV/4      # )zagent.terminal.outputÚ
process_idÚchunk)r¹   rÚ   )r   r-  r(  s   &&€r
   r5   Ú%_wire_desktop_sinks.<locals>.<lambda>2  s&   ø€ ¼EØ#¡Z°Ó%8¸<ÈÏÉÐU\Ð^cÐ:dô=fr   Úon_closec                ó.   <€ \        R S! V 4      RV/4      # )zterminal.closer,  r¸   )r   Úpidr(  s   &&€r
   r5   r.  5  s   ø€ ¼Ð?OÑQ[Ð\cÓQdÐgsÐuxÐfyÔ9zr   )Ú
desktop_uic                ó   € \        WV4      # rV   r¸   )r   rà  rÑ   s   &&&r
   r5   r.  9  s   € ¼uÀUÐQXÔ?Yr   T)r  r  rý   r*  r/  Ú_desktop_ui_wiredrð   rñ   r   rý  r2  Úset_emitter)r  r2  r(  s     @r
   Ú_wire_desktop_sinksr6  #  s‹   ø€ õ
 8õuô Ð ¨dÓ3Ò;ô&fÐÔ"äÐ ¨TÓ2Ò:Ü$zÐÔ!ßÓÜ× Ò ¤×+Õ+Ý(Ø×"Ñ"Ñ#YÔZØ $Ð÷ ,Ñ+ñ ß+×+Ð+ús   Á0BÂB(	r`  Ú_notification_pollersc               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   r   r   r   rñ  r   )r   s   "r
   r   r   B  s!   € ÷ ñ  Cð °$ð ¸?ñ r   c                ó8  € \        4        \        P                  4       p\        P                  \        W V3RRV  2R7      p\
         UUu. uF   w  rEVP                  4       '       g   K  WE3NK"  	  uppW#3.,           \
        R&   VP                  4        V# u uppi )zVStart the background notification poller for a TUI session (thread name is greppable).Tztui-notif-poller-)ÚtargetÚargsÚdaemonrÀ   :NNN)r6  Ú	threadingÚEventÚThreadrô  r7  Úis_aliveÚstart)r   r   Ústopr;  r#   Úths   &&    r
   Ú_start_notification_pollerrD  B  s—   € äÔÜ�?‰?Ó€DÜ×ÑÔ 9ÀÈGÐ@TÐ]aÐj{Ð|ð  |Að  iBÐó  	C€AÝ7LÔ^Ñ7L©G¨QÐPR×P[ÑP[×P]¤ £Ñ7LÒ^ÐcgÐbkÐalÕlÔ˜!ÑØ‡G�G„IØ€Kùó  _s   Á
BÁ)Bc               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   r   r   )r   s   "r
   r   r   L  s   € ÷ +ñ +˜tð +¨ñ +r   c                ó"  € ^ RI Hp V P                  R4      V P                  R4      r2\        VRR4      ;'       g    \	        4       pVR8X  d'   ^ RIHp WT9   d   ^ RIHp ^ R	I	H
p V! WG! V4      4      # R
VRV P                  R4      /pV! W„4      # )z²The per-surface note for this turn ("" for the plain app window): HUD -> the read-the-window-below
prior; voice-live -> the spoken-delegation contract with the recent transcript.)Úsurface_noteÚclient_surfacer  Úvalid_tool_namesNÚhud)ÚTOOL_CALL_NAME)Úhud_surface_note)Ú_tool_search_scoped_namesÚsurfaceÚvoice_contextÚvoice_live_context)Úgateway.session_surfacerG  r   rý   r   Útools.tool_search_catalogrK  Úagent.prompt_builderrL  Úagent.tool_executorrM  )	r   rG  rN  r  ÚdirectrK  rL  rM  Ú	committeds	   &        r
   Ú_hud_surface_noterW  L  s‰   € õ 5Ø—[‘[Ð!1Ó2°G·K±KÀÓ4HˆUÜ�UÐ.°Ó5×>Ð>¼»€FØ�%ÔÝ<ØÔ#õ >ÝEÙ# FÐ,EÀeÓ,LÓMÐMØ˜G _°g·k±kÐBVÓ6WÐX€IÙ˜	Ó*Ð*r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úrun_messager!  Únoter   r   r   )r   s   "r
   r   r   ^  s!   € ÷ ñ ˜sð ¨#ð °#ñ r   c                óž   € V'       d   \        V \        4      '       d   V RV  2# V'       d    \        V \        4      '       d
   RRRV/.V O# V # )u$  Prefix a per-turn note onto the MODEL INPUT, leaving the prompt alone: everything the model must know that the
user did not type (interrupted reply, reactions, surface) arrives this way, so no scaffolding reaches the
transcript and no sent message is rewritten â€” the cached prefix survives.z

r\   r¬   )r¡  r   r`  )rY  rZ  s   &&r
   Ú_prepend_noter\  ^  sP   € ÷ ”
˜;¬×,Ò,Ø��t˜K˜=Ð)Ð)ß”
˜;¬×-Ò-Ø˜ ¨Ð.Ð=°Ð=Ð=ØÐr   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r
   r   r   i  s   € ÷ 0ñ 0˜ñ 0r   c                ó2   € \        \        4       V RR7       R# )zQPublish this module's helpers + handlers onto ``server``, rebound to its globals.)ÚskipN)Ú_)r   Úglobals)Úservers   &r
   Úregisterrc  i  s   € ä”“	˜6¨×/r   rV   )ÚcommandÚpatternrÃ   rv   Ú
message_id)Úseq)rd  rÅ   rv   )r   r€   r�   r‚   rƒ   r„   rj  Ú	unblocked)@Ú__conditional_annotations__Ú__doc__Ú
__future__r   rð   Ú
method_ctxr   r   r!   r'   r7   r>   rK   rH   rW   re   ry   r~   rr  r  r  r‹   r’   rž   r£   r¥   r©   r²   r»   rÔ   rß   rö   rþ   r  r  r  r  r'  r/  r5  rL  rR  r^  r�  rŽ  r’  r‘  r­  rµ  rÅ  rÛ  rè  rí  rô  ró  rÂ  r4  r6  r7  Ú__annotations__rD  rW  r\  rc  )ri  s   @r
   Ú<module>rn     sÝ  øðôGõ #ã å #òõ_õb÷÷õQõ>kõuõ*tð ÐOØ�ØÐ:ØÐ;ð	Ð õoð$ vÐ ð -0Ð /Ð Ð)õ#õ
õQð  Ð Ø3Ð õõõ"@õ4õ8õ*"õJ@õõ,Sõ jõ8õD4õ
)õ5ð �%˜Ð'Ø�ÑvÐwØ�ñ Oð Pà�Ñ^Ð_Ø�%˜Ð'ØˆvÑJÐKðÐ õ
]õ$õ'õT[õ80õ
oô:8õCõ$(ñN?Ðhm÷ ?ð ?òD,.ð^OÐY^ô OõCõ
9!õx^ð Ð õ%ð8 !Ð �tÓ  õõ+õ$÷0r   