+
    „WÝj–l  ã                  óv  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
t
^ RIt^ RIHt ^ RIHt ^ RIHtHt ^ RIHt ^ RIHtHtHt ^ RIHt ]P6                  ! ]4      tR	tR
tRt ]!! 0 RWm4      t"]"R0,
          t#]PH                  ! 4       R8H  t%Rs&]
PN                  ! 4       t(RXR R llt)R R lt*RXR R llt+]! RR7       ! R R4      4       t,RR/R R llt-RR/R R llt.R R lt/] ! R R 4      4       t0R! R" lt1R# R$ lt2R% R& lt3R' R( lt4R)R*/R+ R, llt5RRR-R/R. R/ llt6RXR0 R1 llt7]! R2R*R37      t8R4]9R5&   ]R6 R7 l4       t:R8 R9 lt;R: R; lt<R< R= lt=R> R? lt>R@ RA lt?RR/RB RC llt@RRRDR*RER*/RF RG lltARH RI ltBRJ RK ltCRL RM ltDRNR/RO RP lltERRRNR/RQ RR lltFRS RT ltGRU RV ltHR# )Yu-  Process identity: spawn tags, the machine-wide spawn ledger, and the Windows job-object self-attach.

Three layers make every long-lived Hermes process positively identifiable, so reapers (``hermes
update``, Desktop startup sweeps) never guess lineage from PPID archaeology or cmdline matching:
1. spawn tags (``HERMES_SPAWN`` env stamped by the spawner); 2. a ``(pid, create_time)`` ledger;
3. Windows job-object self-attach with ``KILL_ON_JOB_CLOSE`` so the whole child tree dies with the
root â€” no launcherâ†’worker chains left holding ``.pyd`` locks.
)ÚannotationsN)Úcontextmanager)Ú
ContextVar)ÚasdictÚ	dataclass)ÚPath)ÚIteratorÚOptionalÚSequence)Úatomic_json_writeÚHERMES_SPAWNÚv1zspawn-ledger.jsonú
mcp-helperÚWindowsc               ó    € V ^8„  d   QhRRRR/# )é   Úproject_rootúOptional[Path]ÚreturnÚstr© )Úformats   "ÚOC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\process_identity.pyÚ__annotate__r   2   s   € ÷ Qñ Q˜^ð Q°sñ Qó    c                óÞ  € V f    ^ RI Hp \        V4      p  \        \        V 4      P                  4       4      P                  4       p\        P                  ! VP                  RR4      4      P                  4       R,          #   \         d5    \        \        4      P                  4       P                  P                  p  Lªi ; i  \         d    \        T 4      P                  4       p L£i ; i)zBStable 12-hex identifier for THIS install (derived from its path).)ÚPROJECT_ROOTzutf-8Úreplace:Né   N)Úhermes_constantsr   r   Ú	ExceptionÚ__file__ÚresolveÚparentr   ÚlowerÚOSErrorÚhashlibÚsha256ÚencodeÚ	hexdigest)r   Ú_rootÚ	canonicals   &  r   Ú
install_idr,   2   sÀ   € àÒð	BÝ>ä ›;ˆLð.Üœ˜\Ó*×2Ñ2Ó4Ó5×;Ñ;Ó=ˆ	ô �>Š>˜)×*Ñ*¨7°IÓ>Ó?×IÑIÓKÈCÕPÐPøô ô 	BÜ¤›>×1Ñ1Ó3×:Ñ:×AÑAŠLð	Bûô ô .Ü˜Ó%×+Ñ+Ó-Š	ð.ús"   †B ˜0C Â<CÃCÃ$C,Ã+C,c               ó   € V ^8„  d   QhRR/# )r   r   Úfloatr   )r   s   "r   r   r   B   s   € ÷ %ñ %˜5ñ %r   c                óÞ   € ^ RI p\        VRR4      '       d.   \        V RR4      pVe    \        VP                  RR7      4      # \        V P                  4       4      #   \         d     L&i ; i)aþ  A managed worker's identity birth for the ``psutil.Process`` *proc*, the same in every process.

On macOS psutil shifts ``create_time()`` by ``abs(INIT_BOOT_TIME - boot_time())``
(``psutil._psosx.adjust_proc_create_time``), with a boot-time reference frozen when psutil
was imported in the CALLING process. After a clock step (NTP, sleep/wake) a long-lived
gateway owner and a freshly spawned worker read different births for the same process, and
the exact identity match refused every managed worker (#140580). The kernel's own start
(``monotonic=True``: the unadjusted ``kinfo_proc`` epoch start) is what every process sees.
Other platforms keep ``create_time()``: Linux and Windows apply no per-process reference.
Raises ``psutil.Error`` like ``create_time()``.
NÚMACOSFÚ_procT)Ú	monotonic)ÚpsutilÚgetattrr.   Úcreate_timeÚ	TypeError)Úprocr3   Úplatform_procs   &  r   Úprocess_birthr9   B   sr   € ó Üˆv�w ×&Ò&Ü  g¨tÓ4ˆØÒ$ðÜ˜]×6Ñ6ÀÐ6ÓFÓGÐGô �×!Ñ!Ó#Ó$Ð$øô ô Ùðús   ªA ÁA,Á+A,c               ó    € V ^8„  d   QhRRRR/# )r   ÚpidúOptional[int]r   úOptional[float]r   )r   s   "r   r   r   Y   s   € ÷ ñ ˜mð °ñ r   c                ó¦   €  ^ RI p\        TP                  V f   \        P                  ! 4       4      4      # T 4      4      #   \
         d     R# i ; i)zY:func:`process_birth` of ``pid`` (default: this process); ``None`` when psutil can't say.N)r3   r9   ÚProcessÚosÚgetpidr    )r;   r3   s   & r   Ú_process_create_timerB   Y   sE   € ðÛä˜VŸ^™^¸3º;¬B¯IªI«KÓPÓQÐQÈCÓPÓQÐQøÜô Úðús   ‚4A ·	A ÁAÁAT)Úfrozenc                  ó@   € ] tR t^ft$ R]R&   R]R&   R]R&   R]R&   RtR	# )
ÚSpawnTagr   ÚinstallÚpurposeÚintÚspawner_pidr=   Úspawner_creater   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__annotations__Ú__static_attributes__r   r   r   rE   rE   f   s   ‡ àƒLØƒLØÓØ#×#r   rE   r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rG   r   r   r   r   r   )r   s   "r   r   r   n   s&   € ÷ fñ f˜Sð f°>ð fÈSñ fr   c          	     ó¨   € \        4       pVe   VR MRpRP                  \        \        V4      V \	        \
        P                  ! 4       4      V34      # )zGValue for the child's ``HERMES_SPAWN`` env var, stamped by the spawner.z.3fÚ-Ú:)rB   ÚjoinÚ_TAG_VERSIONr,   r   r@   rA   )rG   r   ÚcreateÚcreate_parts   &$  r   Úbuild_spawn_tagrY   n   sE   € ä!Ó#€FØ%+Ò%7�V˜C‘L¸S€KØ�8‰8”\¤:¨lÓ#;¸WÄcÌ"Ï)Ê)Ë+ÓFVÐXcÐdÓeÐer   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rG   r   r   r   r   zdict[str, str]r   )r   s   "r   r   r   u   s&   € ÷ Pñ P�sð P¨^ð PÀ~ñ Pr   c               ó&   € \         \        WR7      /# )z9Env fragment a spawner merges into a child's environment.©r   )ÚSPAWN_ENV_VARrY   )rG   r   s   &$r   Ú	spawn_envr^   u   s   € äœ?¨7ÔNÐOÐOr   c               ó    € V ^8„  d   QhRRRR/# )r   ÚrawÚobjectr   zOptional[SpawnTag]r   )r   s   "r   r   r   z   s   € ÷ Hñ H˜ð HÐ$6ñ Hr   c                óZ  € \        V \        4      '       d   V P                  R4      M. p\        V4      ^8w  g   V^ ,          \        8w  d   R# Vw  r#rEpV'       d	   V'       g   R#  \        V4      pVR8X  d   RM
\        V4      pT^ 8”  d   \        Y4Yx4      # R#   \         d     R# i ; i)z@Parse a ``HERMES_SPAWN`` value; ``None`` for anything malformed.rT   NrS   )	Ú
isinstancer   ÚsplitÚlenrV   rH   r.   Ú
ValueErrorrE   )	r`   ÚpartsÚ_rF   rG   Úpid_sÚcreate_sr;   rW   s	   &        r   Úparse_spawn_tagrk   z   s—   € ä(¨¬c×2Ò2ˆC�I‰I�cŒN¸€EÜ
ˆ5ƒz�Q„˜% �(¤lÔ2ÙØ+0Ñ(€A� ßŸ'ÙðÜ�%‹jˆØ! Sœ‘¬e°H«oˆð 7:¸A´gŒ8�G cÓ2ÐGÀ4ÐGøô ô Úðús   Á'B ÂB*Â)B*c                  ó®   € ] tR t^�t$ R]R&   R]R&   R]R&   R]R&   R]R	&   R]R
&   R]R&   R]R&   RtR]R&   RtR]R&   RtR]R&   RtR]R&   Rt	R]R&   Rt
R# )ÚLedgerEntryrH   r;   r=   r5   r   rG   rF   r<   rI   rJ   r.   Úregistered_atÚargvÚ ÚhostNÚportÚprofileÚhermes_homeFÚboolÚisolatedr   )rK   rL   rM   rN   rO   rq   rr   rs   rt   rv   rP   r   r   r   rm   rm   �   sc   ‡ à	ƒHØ Ó ØƒLØƒLØÓØ#Ó#ØÓØ
ƒIð €Dˆ#ƒNØ€Dˆ-ÓØ€GˆSÓØ€K�Óð €Hˆd×r   rm   c               ó   € V ^8„  d   QhRR/# )r   r   r   r   )r   s   "r   r   r   ¢   s   € ÷ 	9ñ 	9�dñ 	9r   c                 óª   €  ^ RI Hp  \        V ! 4       4      \        ,          #   \         d%    ^ RIHp \        T! 4       4      \        ,          u # i ; i)zCMachine-root ledger path (shared by every profile of this install).)Úget_default_hermes_root)Úget_hermes_home)r   ry   r   ÚLEDGER_FILENAMEr    Úhermes_cli.configrz   )ry   rz   s     r   Ú_ledger_pathr}   ¢   sC   € ð9Ý<äÑ+Ó-Ó.´Õ@Ð@øÜô 9Ý5ä‘OÓ%Ó&¬Õ8Ò8ð9ús   ‚ # £,AÁAc               ó    € V ^8„  d   QhRRRR/# ©r   Úpathr   r   zOptional[list[dict]]r   )r   s   "r   r   r   ®   s   € ÷ \ñ \�tð \Ð 4ñ \r   c                ó�  €  V P                  RR7      pTP	                  4       '       g   . #  \
        P                  ! T4      p\        T\        4      '       d+   T Uu. uF  p\        T\        4      '       g   K  TNK  	  up# R#   \         d    . u # \        \        3 d     R# i ; i  \        \        3 d     R# i ; iu upi )zÑEntries list, ``[]`` for empty/missing, ``None`` for CORRUPT (never silently an empty roster).

Mirrors the #89298 contract: corrupt is a distinct state that must never be silently treated as an empty
roster.
z	utf-8-sig)ÚencodingN)Ú	read_textÚFileNotFoundErrorr%   ÚUnicodeErrorÚstripÚjsonÚloadsrf   r6   rc   ÚlistÚdict)r€   ÚtextÚparsedÚes   &   r   Ú_read_ledgerrŽ   ®   s±   € ðØ�~‰~ {ˆ~Ó3ˆð
 �:‰:�<Š<Øˆ	ðÜ—’˜DÓ!ˆô :DÀFÌD×9QÒ9Q‘vÓ5‘v�!¤¨A¬t×!4�AˆA‘vÑ5Ð[ÐW[Ð[øô ô ØŠ	Ü”\Ð"ô Úðûô œ	Ð"ô Úðüâ5s:   ‚B ­B+ ÁCÁ:CÂB(ÂB(Â#B(Â'B(Â+C Â?C c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r   Ã   s   € ÷ 
ñ 
 Tð 
Ð.Bñ 
r   c                óê   € \        V 4      pVfR   V P                  V P                  R,           4      p \        P                  ! W4       \
        P                  RV4       V# V#   \         d     T# i ; i)zULedger entries; ``None`` after parking a corrupt file. Caller holds ``_LEDGER_LOCK``.z.corruptz(spawn ledger was unreadable; moved to %s)rŽ   Úwith_suffixÚsuffixr@   r   ÚloggerÚwarningr%   )r€   ÚentriesÚparkeds   &  r   Ú_read_ledger_or_quarantiner—   Ã   sn   € ä˜4Ó €GØ‚Ø×!Ñ! $§+¡+°
Õ":Ó;ˆð	Ü�JŠJ�tÔ$Ü�N‰NÐEÀvÔNð €Nˆ7€Nøô ô 	ØØ€Nð	ús   ³,A# Á#A2Á1A2c               ó    € V ^8„  d   QhRRRR/# )r   r5   r=   r   ru   r   )r   s   "r   r   r   Ð   s   € ÷ Vñ V¨ð V¸Tñ Vr   c                óh   € VRJ ;'       g(    \        \        V 4      \        V4      ,
          4      R8  # )zZDoes the live ``proc`` match a recorded ``create_time`` (2 s tolerance; ``None`` matches)?Nç       @)Úabsr9   r.   )r7   r5   s   &&r   Ú_same_incarnationrœ   Ð   s/   € à˜$Ð×UÐU¤#¤m°DÓ&9¼EÀ+Ó<NÕ&NÓ"OÐRUÑ"UÐUr   ÚstrictFc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r;   rH   r5   r=   r�   ru   r   úOptional[bool]r   )r   s   "r   r   r   Õ   s)   € ÷ ñ ˜Cð ¨oð È$ð Ð[iñ r   c               ó  €  ^ RI p TP                  \        T 4      4      pT'       dX   TRJ;'       dL    \	        T4      T8H  ;'       d6    TP                  4       ;'       d    TP                  4       TP                  8g  # \        YA4      ;'       d:    \        P                  R8H  ;'       g    TP                  4       \        TRR4      8g  #   \         d     R# i ; i  TP                   d     R# \         d     R# i ; i)z9True/False when provable; ``None`` when psutil can't say.NÚntÚSTATUS_ZOMBIEÚzombieF)r3   r    r?   rH   r9   Ú
is_runningÚstatusr¢   rœ   r@   Únamer4   ÚNoSuchProcess)r;   r5   r�   r3   r7   s   &&$  r   Ú_pid_alive_matchesr¨   Õ   sü   € ðÛðØ�~‰~œc #›hÓ'ˆßØ tÐ+÷ Tð T´¸dÓ0CÀ{Ñ0R÷ Tð TØŸ™Ó)÷Tð TØ.2¯k©k«m¸v×?SÑ?SÑ.SðUô
 ! Ó3÷ \ð \Ü�G‰G�t‰O×ZÐZ˜tŸ{™{›}´¸ÀÐQYÓ0ZÑZð	\øô ô Úðûð ×Ñô ÚÜô ÚðúsQ   ‚C ‡,C ´C Á
C Á"C Â C ÂC Â-C ÃCÃCÃD Ã2D Ã;D Ã?D Údetailc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   rG   r   r   r   r©   úOptional[dict]r   ru   r   )r   s   "r   r   r   ë   s*   € ÷  ñ  ˜3ð  °ð  ÐP^ð  Ðjnñ  r   c               ó2  € ^ RI Hp \        \        P                  P                  \        4      4      pV'       d   VP                  VP                  3M	\        4       w  rV\        \        P                  ! 4       \        4       WWV4      pV! 4       Vn        V'       dŸ    \        VP                  R4      ;'       g    R4      Vn        VP                  R4      e   \!        VR,          4      MRVn        \        VP                  R4      ;'       g    R4      Vn        \'        VP                  R4      4      Vn         ^ RIpRP1                  VP2                  R	,          4      Vn        \7        V4      #   \*        \,        3 d     LJi ; i  \4         d     L/i ; i)
až  Record this process in the machine spawn ledger. Best-effort.

Called at the top of every long-lived entry point; dead ``(pid, create_time)`` entries are
pruned on every write. ``detail`` may carry ``host``/``port``/``profile`` so the update
pipeline can relaunch a manually-started serve with its real bind address, and ``isolated``
so attach-first discovery skips a backend that opted out of the host singleton.
)Úhermes_home_keyrq   rp   rr   Nrs   rv   Ú ºNé
   N)r   r­   rk   r@   ÚenvironÚgetr]   rI   rJ   Ú_desktop_spawner_identityÚ
_new_entryrA   rB   rt   r   rq   rH   rr   rs   ru   rv   r6   rf   ÚsysrU   ro   r    Ú_append_entry)	rG   r   r©   r­   ÚtagrI   rJ   ÚentryÚ_syss	   &$$      r   Úregister_selfrº   ë   s6  € õ 1ä
œ"Ÿ*™*Ÿ.™.¬Ó7Ó
8€CßKN 3§?¡?°C×4FÑ4FÑ"GÔTmÓToÑ€KÜ”r—y’y“{Ô$8Ó$:¸GÐS^Óo€EÙ'Ó)€EÔßð	Ü˜VŸZ™Z¨Ó/×5Ð5°2Ó6ˆEŒJØ06·
±
¸6Ó0BÒ0Nœ˜V F�^Ô,ÐTXˆEŒJÜ §
¡
¨9Ó 5× ;Ð ;¸Ó<ˆEŒMÜ! &§*¡*¨ZÓ"8Ó9ˆEŒNðÛð —X‘X˜dŸi™i¨�nÓ-ˆŒ
ô ˜ÓÐøô œ:Ð&ô 	Ùð	ûô ô Ùðús1   ÂE1 Â:AE1 Ä+E1 Ä;+F Å1FÆFÆFÆFc               ó    € V ^8„  d   QhRRRR/# )r   ro   zOptional[Sequence[str]]r   ru   r   )r   s   "r   r   r     s   € ÷ Uñ UÐ#:ð UÀdñ Ur   c                ó  € \         P                  P                  R4      R8w  d   R# \         P                  P                  R4      '       d   R# ^ RIHp T! \        V f    \        P                  R,          4      4      # T 4      4      # )a&  Whether this process is the backend Desktop spawned and owns.

``HERMES_DESKTOP=1`` is inherited by every shell and agent child the app launches, so the
flag alone is not ownership proof (same class as #116107). Desktop hands its backend a
per-spawn credential the terminal pane never receives (and the terminal tool's env policy
strips from agent children): the local pool spawn mints ``HERMES_DASHBOARD_SESSION_TOKEN``,
the SSH spawn passes a 0600 token FILE on argv and deliberately sets no token env var.
``argv`` defaults to this process's own.
ÚHERMES_DESKTOPÚ1FÚHERMES_DASHBOARD_SESSION_TOKENT)Úis_desktop_ssh_backend_argv:é   NN)r@   r±   r²   Úhermes_cli._startup_fastrÀ   r‰   rµ   ro   )ro   rÀ   s   & r   Úis_desktop_owned_backendrÃ     s^   € ô 
‡z�z‡~�~Ð&Ó'¨3Ô.ÙÜ	‡z�z‡~�~Ð6×7Ò7ÙÝDá&¤t¸DºL¬C¯H©H°R­LÓ'SÓTÐTÈdÓ'SÓTÐTr   Úhermes_serving_local_desktop)ÚdefaultzContextVar[bool]Ú_SERVING_LOCAL_DESKTOPc               ó    € V ^8„  d   QhRRRR/# )r   Úactiveru   r   zIterator[None]r   )r   s   "r   r   r   &  s   € ÷ ,ñ , $ð ,¨>ñ ,r   c              #  óê   "  € \         P                  \        V 4      ;'       g    \         P                  4       4      p Rx € \         P	                  V4       R#   \         P	                  T4       i ; i5i)z_Mark the enclosed activity (and threads it hands its context to) as work for the local Desktop.N)rÆ   Úsetru   r²   Úreset)rÈ   Útokens   & r   Úserving_local_desktoprÍ   %  sR   é € ô #×&Ñ&¤t¨F£|×'SÐ'SÔ7M×7QÑ7QÓ7SÓT€Eð,Ûä×$Ñ$ UÖ+øÔ×$Ñ$ UÕ+üs   ‚;A3¾A ÁA3ÁA0Á0A3c               ó   € V ^8„  d   QhRR/# ©r   r   ru   r   )r   s   "r   r   r   /  s   € ÷ (ñ ( $ñ (r   c                 ó*   € \         P                  4       # ©N)rÆ   r²   r   r   r   Úserves_local_desktop_nowrÒ   /  s   € Ü!×%Ñ%Ó'Ð'r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úidentityr«   Údeclaredra   r   ru   r   )r   s   "r   r   r   3  s!   € ÷ :ñ : >ð :¸Vð :Èñ :r   c                ó¨   € VRJ ;'       dH    \        V \        4      ;'       d0    V P                  R4      R8H  ;'       d    V P                  R4      RJ # )aŒ  A connected client is the Desktop app on this machine when it says so (it knows its connection
mode) AND it redeemed a native ticket, which only this machine's private control socket mints, for
this OS user. Neither alone: the CLI and TUI hold native tickets too, and the claim is the client's
word. A remote Desktop reaches a backend through SSH, URL or Cloud credentials, never a native ticket.TÚproviderÚlocalÚnative_bootstrap)rc   rŠ   r²   )rÔ   rÕ   s   &&r   Úlocal_desktop_clientrÚ   3  s[   € ð
 ˜Ð÷ 9ð 9¤¨H´dÓ!;÷ 9ð 9ÀÇÁÈZÓ@XÐ\cÑ@c÷ 9ð 9Ø—‘Ð/Ó0°DÐ8ð:r   c               ó   € V ^8„  d   QhRR/# )r   r   z%tuple[Optional[int], Optional[float]]r   )r   s   "r   r   r   <  s   € ÷ !ñ !Ð#Hñ !r   c                 óž  €  \        \        P                  P                  RR4      4      p V ^ 8:  d   R# \        P                  P                  RR4      pVP                  R4      '       g   V R3#  V \        VP                  R^4      ^,          4      R,          3#   \        \
        3 d    ^ p  L…i ; i  \
        \        3 d    T R3u # i ; i)	zýSpawner ``(pid, create_time)`` from the Electron app's HERMES_PARENT_PID (+ optional
``winms:<ms>`` start marker) parent-death watchdog vars, so ledger lineage works with every
Desktop version without a TS change. ``(None, None)`` when absent/malformed.ÚHERMES_PARENT_PIDrp   NÚHERMES_PARENT_START_MARKERzwinms:rT   g     @�@)NN)
rH   r@   r±   r²   r6   rf   Ú
startswithr.   rd   Ú
IndexError)rI   Úmarkers     r   r³   r³   <  sÇ   € ðÜœ"Ÿ*™*Ÿ.™.Ð)<¸bÓAÓBˆð �aÔØÐÜ�Z‰Z�^‰^Ð8¸"Ó=€FØ×Ñ˜X×&Ò&Ø˜DÐ Ð ð!ØœE &§,¡,¨s°AÓ"6°qÕ"9Ó:¸VÕCÐCÐCøô ”zÐ"ô ØŠðûô œ
Ð#ô !Ø˜DÐ Ò ð!ús#   ‚)B Á0*B4 ÂB1Â0B1Â4CÃCc               ó4   € V ^8„  d   QhRRRRRRRRR	R
RRRR/# )r   r;   rH   r5   r=   rG   r   r   r   rI   r<   rJ   r   rm   r   )r   s   "r   r   r   O  sF   € ÷ ñ Ø	ðØ*ðØ58ðØHVðàðà0?ðð ñr   c                ó\   € \        WV\        V4      WE\        P                  ! 4       R R7      # )rp   )ro   )rm   r,   Útime)r;   r5   rG   r   rI   rJ   s   &&&&&&r   r´   r´   O  s.   € ô Ø˜'¤:¨lÓ#;¸[ÔZ^×ZcÒZcÓZeÐlnôð r   c               ó    € V ^8„  d   QhRRRR/# )r   r¸   rm   r   ru   r   )r   s   "r   r   r   X  s   € ÷ ñ ˜ð ¨ñ r   c                ó~  € \        4       p\        ;_uu_ 4        \        V4      ;'       g    . pV Uu. uFn  p\        VP	                  R4      \
        4      '       g   K*  VR,          V P                  8w  g   KD  \        VR,          VP	                  R4      4      RJg   Kl  VNKp  	  ppVP                  \        V 4      4        ^ RI
Hp V! VP                  4       \        WRRR7        RRR4       R# u upi   \         d$    \        P!                  R	RR
7        RRR4       R# i ; i  + '       g   i     R# ; i)uÆ   Prune dead entries and append ``entry`` â€” the ONLY ledger write path.

Serialized under ``_LEDGER_LOCK`` with an atomic tmp+replace; no writer touches the file
outside this function.

See #91660.
r;   r5   F)Úmkdir_under_hermes_homei€  T)ÚmodeÚensure_asciiNzspawn ledger write failed©Úexc_info)r}   Ú_LEDGER_LOCKr—   rc   r²   rH   r;   r¨   Úappendr   r   rç   r#   r   r%   r“   Údebug)r¸   r€   r•   r�   Úprunedrç   s   &     r   r¶   r¶   X  s  € ô ‹>€Dß	ŽÜ,¨TÓ2×8Ð8°bˆñ ó
Ù�!Ü˜!Ÿ%™% ›,¬×,ô à�%•˜EŸI™IÑ%ô ô # 1 U¥8¨Q¯U©U°=Ó-AÓBÈ%ÐO÷ ˆA‘wð 	ð 
ð 	�‰”f˜U“mÔ$ð		Ý@Ù# D§K¡KÔ0ô ˜d°ÀTÕJØ÷! 
‰ùò
øô ô 	Ü�L‰LÐ4¸tˆLÔDØ÷' 
‰ð"	ú÷# 
�ˆúsL   ™D+³'C5ÁC5Á9#C5Â!C5Â'D+Ã&C:Ã5D+Ã:"D(ÄD+Ä'D(Ä(D+Ä+D<	c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r;   rH   rG   r   r   r   r   ru   r   )r   s   "r   r   r   w  s)   € ÷  ñ  ˜ð   cð  ¸Nð  ÐVZñ  r   c          	     ó†  €  \        V 4      p T ^ 8”  d   \        T 4      MRpTf   R# \	        YY\
        P                  ! 4       \        4       4      p ^ RIpRP                  TP                  T 4      P                  4       R,          4      Tn        \        T4      #   \        \        3 d     R# i ; i  \         d     L0i ; i)a–  Record a CHILD process this process just spawned. Best-effort.

Mirror of :func:`register_self` for children that cannot register themselves (stdio MCP
helpers: arbitrary ``npx``/binary servers never import Hermes code). Records the child's
``(pid, create_time)`` with THIS process as spawner, so a helper whose spawner is provably gone
is a reapable orphan and one whose spawner is alive is never reaped.
FNr®   r¯   )rH   r6   rf   rB   r´   r@   rA   r3   rU   r?   Úcmdlinero   r    r¶   )r;   rG   r   Úchild_creater¸   r3   s   &&$   r   Úregister_childrô   w  s°   € ðÜ�#‹hˆð 14°a´Ô'¨Ô,¸T€LØÒÙÜ�s¨'ÄÇÂÃÔNbÓNdÓe€EðÛà—X‘X˜fŸn™n¨SÓ1×9Ñ9Ó;¸CÕ@ÓAˆŒ
ô ˜ÓÐøô ”zÐ"ô Úðûô ô Ùðús#   ‚B Á>B2 ÂB/Â.B/Â2C Â?C Úall_installsÚverified_onlyc               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r   r   rõ   ru   rö   r   z
list[dict]r   )r   s   "r   r   r   �  s,   € ÷ ñ Ø#ðØ:>ðØW[ðàñr   c           	     ó  € \        V 4      p\        ;_uu_ 4        \        \        4       4      pRRR4       Xf   . # V Uu. uF§  pV'       g   VP	                  R4      V8X  g   K#  \        VP	                  R4      \        4      '       g   KJ  V'       d,   \        VR,          VP	                  R4      RR7      RJ g   K|  M(\        VR,          VP	                  R4      4      RJg   K¥  VNK©  	  up#   + '       g   i     LÊ; iu upi )uN  Ledger entries for this install, or all installs when explicitly requested.

``verified_only`` requires an exact live PID/create-time pair. The default preserves
unknown processes for reapers, which must not mistake missing proof for a dead process.

Entries whose ``(pid, create_time)`` no longer matches a live process are excluded (PID reuse reads as
dead, thanks to the create-time pair). A corrupt ledger is quarantined and read as empty â€” identical
philosophy to the backend-ownership fix (#89298): never let corruption erase or fake a roster; never let
it block the caller either.
NrF   r;   r5   T)r�   F)r,   rì   r—   r}   r²   rc   rH   r¨   )r   rõ   rö   Úwant_installr•   r�   s   $$$   r   Úledger_entriesrú   �  sØ   € ô ˜lÓ+€Lß	ŽÜ,¬\«^Ó<ˆ÷ 
à‚Øˆ	áóÙˆaß˜AŸE™E )Ó,°Ñ<ô 	
ä�q—u‘u˜U“|¤S×)ô 	
÷ ô    %¥¨!¯%©%°Ó*>ÀtÔLÐPTÐTô 	
ð UÜ#5°a¸µhÀÇÁÀmÓ@TÓ#UÐ]bÐ#b÷	 	
ˆ‘7ñð ÷	 
�üòs5   šC0Á DÁDÁ%"DÂDÂ%DÂ>$DÃ'DÃ0D 	c               ó    € V ^8„  d   QhRRRR/# )r   r¸   rŠ   r   rŸ   r   )r   s   "r   r   r   «  s   € ÷ 0ñ 0˜4ð 0 Nñ 0r   c                ó°   € V P                  R4      p\        V\        4      '       d   V^ 8:  d   R# \        WP                  R4      4      pVf   R# V'       * # )zYIs the recorded spawner of this entry provably gone? ``None`` when unrecorded/unprovable.rI   NrJ   )r²   rc   rH   r¨   )r¸   rI   Úalives   &  r   Úspawner_is_deadrþ   «  sL   € à—)‘)˜MÓ*€KÜ�k¤3×'Ò'¨;¸!Ô+;ÙÜ˜{¯I©IÐ6FÓ,GÓH€EØ’=ˆ4Ð/¨%¤iÐ/r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r;   rH   r5   r=   r   ru   r   )r   s   "r   r   r   ´  s!   € ÷ ñ ˜cð °ð ÀDñ r   c                óB  €  ^ RI pVP                  V 4      p\        W14      '       g   R# VP                  4         VP	                  RR7       R#   TP
                   d    TP                  4         R# i ; i  \         d    \        P                  RT RR7        R# i ; i)zYSIGTERM, 2 s grace, then SIGKILL. False when the incarnation moved on or is already gone.NFrš   ©ÚtimeoutTz"orphan terminate failed for pid %srê   )
r3   r?   rœ   Ú	terminateÚwaitÚTimeoutExpiredÚkillr    r“   rî   )r;   r5   r3   r7   s   &&  r   Ú_terminate_then_killr  ´  s‘   € ðÛà�~‰~˜cÓ"ˆÜ  ×3Ò3ÙØ�‰Ôð	Ø�I‰I˜cˆIÔ"ñ øð ×$Ñ$ô 	Ø�I‰I�KÙð	ûô ô Ü�‰Ð9¸3ÈˆÔNÚðús3   ‚&A7 ªA7 »A Á!A4Á0A7 Á3A4Á4A7 Á7#BÂBc               ó    € V ^8„  d   QhRRRR/# )r   r;   rH   r   ru   r   )r   s   "r   r   r   Ç  s   € ÷ ñ ˜Cð  Dñ r   c                ó  €  ^ RI HpHpHp V! V 4      R9  d   R# Y! 4       ;'       g    R9   d   R# ^ RIp^ RIp\        RVP	                  4       VP                  V 4      P                  4       ,
          4      V8¬  #   \         d     R# i ; i)u½  Null-spawner owner with no live supervisor: reparented to init, old, lock-unclaimed.

Mirrors ``_reap_orphaned_desktop_local_serves``: operator-managed remote backends legitimately
sit at ppid 1 (systemd, an exited sshd), so ppid alone is never proof â€” the SSH-lock claim
and the 180 s lock-write grace exclude live-supervised backends. Windows: the ppid probe is
unavailable there, so this rung never fires (desktop tree-kill reaps instead).
)Ú_REAP_MIN_AGE_SECONDSÚ_lock_owned_serve_pidsÚ_process_ppidFNg        )é    rÁ   r   )
Úhermes_cli.dashboard_procsr
  r  r  rä   r3   Úmaxr?   r5   r    )r;   r
  r  r  Ú_timer3   s   &     r   Ú_reparented_orphanr  Ç  s‚   € ð÷	Jñ 	Já˜Ó VÔ+ÙØÐ)Ó+×1Ð1¨rÔ2ÙÛãÜ�3˜Ÿ
™
› v§~¡~°cÓ':×'FÑ'FÓ'HÕHÓIÐMbÑbÐbøÜô Úðús!   ‚A; ›A; ©A; ²AA; Á;B
Â	B
Úkill_fnc               ó$   € V ^8„  d   QhRRRRRR/# )r   r;   rH   r5   r=   r   r<   r   )r   s   "r   r   r   Þ  s$   € ÷ -ñ -Ø	ð-Ø*ð-Ø@Mñ-r   c               óv  a a€  \        S 4      o S ^ 8:  g   S \        P                  ! 4       8X  d   R#  \        TT 3R l\        4        4       R4      pTf   R# \        T4      RJd'   TP                  R4      f   \        S 4      '       g   R#  Te
   T! S 4       M$\        S TP                  R4      4      '       g   R#  \        P                  RTP                  R	4      S 4       S #   \        \        3 d     R# i ; i  \         d     R# i ; i  \         d    \        P                  RTRR7        R# i ; i)
uL  Kill the conflicting host owner when the ledger PROVES it is a dead session's orphan.

HELD_BY_OTHER rung for #121964: the owner PID is alive (re-parented to init), so
``record_is_stale()`` never fires and a fresh backend would loop observe-only against the
same orphan forever. Reaped only with a live ``serve``/``dashboard``/``gateway`` entry for
THIS install whose spawner is provably dead â€” or whose spawner was never recorded and which
is reparented to init, old, and claimed by no Desktop SSH lock. Live-spawned, lock-claimed,
young, interactive, self, or unprovable owners are never touched. Returns the reaped pid,
else ``None``; never raises.

# ponytail: a dead session's surviving backend.lock.json still shields its orphan (the lock
# has no session liveness); clearing stale locks is a Desktop-side lifecycle job, not this rung.
Nc              3  ó"  <"  € T F„  pVP                  R 4      S8X  g   K  VP                  R4      \        9   g   K7  VP                  R4      e7   Se3   \        \        VR,          4      \        S4      ,
          4      R8  g   K€  Vx € K†  	  R# 5i)r;   rG   r5   Nrš   )r²   Ú_BACKEND_OWNER_PURPOSESr›   r.   )Ú.0r�   r5   r;   s   & €€r   Ú	<genexpr>Ú.reap_orphaned_backend_owner.<locals>.<genexpr>õ  s~   øé € ð OÑ(�1Ø—‘�e“ Ñ#ô à—‘�yÓ!Ô%<Ñ<ô ð —%‘%˜Ó&Ò.°+Ò2EÜœ˜q Õ/Ó0´5¸Ó3EÕEÓFÈÑL÷	 ŠQÓ(ùs   ƒB B¼ABÂ
BTrI   r5   z backend owner reap failed for %srê   z'reaped orphaned %s backend owner pid %srG   )rH   r6   rf   r@   rA   Únextrú   r    rþ   r²   r  r  r“   rî   Úinfo)r;   r5   r  r¸   s   ff$ r   Úreap_orphaned_backend_ownerr  Þ  s(  ù€ ðÜ�#‹hˆð ˆa„x�3œ"Ÿ)š)›+Ô%Ùð	ÜõOœÔ(ó Oð
 óˆð ‚}ÙÜ�uÓ TÓ)Ø�I‰I�mÓ$Ò,Ô1CÀC×1HÒ1HÙðØÒÙ�C�LÜ% c¨5¯9©9°]Ó+C×DÒDÙð Eô
 ‡K�KÐ9¸5¿9¹9ÀYÓ;OÐQTÔUØ€Jøô9 ”zÐ"ô Úðûô ô Úðûô ô Ü�‰Ð7¸ÈˆÔNÚðús:   „C' ³C? ÂD Â!D Ã'C<Ã;C<Ã?DÄDÄ#D8Ä7D8c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   z	list[int]r   )r   s   "r   r   r     s   € ÷ ,ñ ,¨~ð ,ÐW`ñ ,r   c                óV  € . p \        V R7      p\        P                  ! 4       pT Fñ  p TP	                  R4      pTP	                  R4      R8w  g$   \        T\        4      '       d   T^ 8:  g   Yd8X  d   KP  \        T4      RJd   Ka  Te
   T! T4       Mr^ RIpTP                  T4      p\        Y…P	                  R4      4      '       g   K¥  \        '       d   \        T4       M#TP                  4         TP                  RR	7       TP#                  T4       Kó  	  T'       d!   \$        P)                  R\+        T4      T4       T#   \         d    Tu # i ; i  TP                   d    TP!                  4         Lui ; i  \         d    \$        P'                  R
TRR7        EK€  i ; i)u.  Kill ledger-registered stdio MCP helpers whose spawner is provably dead.

Ledger-driven startup-sweep rung (not cmdline-heuristic): a helper is reaped ONLY when it has a
live ``mcp-helper`` entry for THIS install AND ``spawner_is_dead`` is ``True`` â€” never
``None``/unprovable, never a live spawner.
r\   r;   rG   r   TNr5   rš   r  z$mcp-helper orphan reap failed for %srê   z*reaped %d orphaned stdio MCP helper(s): %s)rú   r    r@   rA   r²   rc   rH   rþ   r3   r?   rœ   Ú_IS_WINDOWSÚ_kill_process_tree_windowsr  r  r  r  rí   r“   rî   r  re   )	r   r  Úreapedr•   Úown_pidr¸   r;   r3   r7   s	   $$       r   Úreap_orphaned_mcp_helpersr#    so  € ð €FðÜ ¨lÔ;ˆô �iŠi‹k€GÛˆð	WØ—)‘)˜EÓ"ˆCØ�y‰y˜Ó# |Ô3¼:ÀcÌ3×;OÒ;OÐSVÐZ[ÔS[Ð_bÔ_mÙÜ˜uÓ%¨TÓ1ÙØÒ"Ù˜•ãà—~‘~ cÓ*�Ü(¨¯y©y¸Ó/G×HÒHÙ÷ “;Ü.¨tÕ4à—N‘NÔ$ð$ØŸ	™	¨#˜	Ô.ð �M‰M˜#Öñ5 ÷: Ü�‰Ð@Ä#ÀfÃ+ÈvÔVØ€MøôE ô ØŠðûð6 "×0Ñ0ô $ØŸ	™	žð$ûô ô 	WÜ�L‰LÐ?ÀÐQUˆL×VÐVð	Wús`   „E «A
F Á7F ÂAF ÃF ÃF Ã5EÄF ÅEÅEÅ!E=Å:F Å<E=Å=F Æ #F(Æ'F(c               ó   € V ^8„  d   QhRR/# )r   r   ÚNoner   )r   s   "r   r   r   @  s   € ÷ ñ ¨ñ r   c                óÚ  € ^ RI p V P                  RR7      pV F  p VP                  4        K  	   V P                  4         VP                  W .,           RR7      w  rET F  p TP                  4        K  	  R#   TP                  TP                  \        3 d    . p LŠi ; i  \         d     Kš  i ; i  \         d     L‚i ; i  \         d     R# i ; i  \         d     K‡  i ; i)u  Terminate *proc* and every still-alive descendant (npx.cmd â†’ node.exe), Windows-only
(#61059): without a pgid there is no group-kill, and grandchildren reparent to nothing
(ParentId=null) once the direct child exits, so they must be reached through the tree.NT)Ú	recursiverš   r  )	r3   Úchildrenr§   ÚAccessDeniedr%   r  r    Ú
wait_procsr  )r7   r3   ÚdescendantsÚchildrh   rý   Úsurvivors   &      r   r   r   @  sö   € ó ðØ—m‘m¨d�mÓ3ˆó ˆð	Ø�O‰OÖñ ð
Ø�‰ÔðØ×$Ñ$ [°6Õ%9À3Ð$ÓG‰ˆó ˆð	Ø�M‰MŽOó øð × Ñ  &×"5Ñ"5´wÐ?ô ØŠðûô
 ô 	Úð	ûô ô Ùðûô ô Úðûô
 ô 	Úð	úsW   †A< žB&³B8 ÁC	 Á&CÁ<$B#Â"B#Â&B5Â4B5Â8CÃCÃ	CÃCÃC*Ã)C*c               ó   € V ^8„  d   QhRR/# rÏ   r   )r   s   "r   r   r   ^  s   € ÷ :ñ :¨$ñ :r   c                 ó  a	a
aa€ \         '       d	   \        e	   \        RJ#  ^ RIo^ RIHo SP	                  RRR7      p RpRpRp^	p ! V3R	 lR
SP
                  4      o	 ! VV3R lRSP
                  4      o
 ! V	V
V3R lRSP
                  4      pV P                  RR4      pV'       g   R# V! 4       pW,          V,          VP                  n        V P                  WdSP                  V4      SP                  V4      4      pV'       d&   V P                  W`P                  4       4      '       g   V P                  V4       R# Vs\        P!                  R4       R#   \"         d    \        P!                  RRR7        R# i ; i)zöPlace this process in a job that dies (whole tree) when we die. Windows-only, idempotent.

``BREAKAWAY_OK`` keeps children spawned with ``CREATE_BREAKAWAY_FROM_JOB`` (gateway relaunch
during update, detached watchers) escaping exactly as before.
N)ÚwintypesÚkernel32T)Úuse_last_errori    i   i   c                  ó\   <€ ] tR tRtR U u. uF  q SP                  3NK  	  up tRtR# u up i )Ú5attach_self_to_kill_on_close_job.<locals>.IO_COUNTERSir  r   N)ÚReadOperationCountÚWriteOperationCountÚOtherOperationCountÚReadTransferCountÚWriteTransferCountÚOtherTransferCount)rK   rL   rM   rN   Úc_ulonglongÚ_fields_rP   )ÚnÚctypess   0€r   ÚIO_COUNTERSr4  r  s7   ø† ñ:Qó Rñ :Q°A˜F×.Ñ.Ó/ñ :Qñ RŒHùò Rs   Œ)r?  c            
      ó8  <€ ] tR tRtR ZP                  3R ZP                  3R ZP
                  3R Z P                  3R Z P                  3R ZP
                  3R Z P                   ZP                  4      3R	 ZP
                  3R
 ZP
                  3.	t	Rt
R# )ÚKattach_self_to_kill_on_close_job.<locals>.JOBOBJECT_BASIC_LIMIT_INFORMATIONiw  ÚPerProcessUserTimeLimitÚPerJobUserTimeLimitÚ
LimitFlagsÚMinimumWorkingSetSizeÚMaximumWorkingSetSizeÚActiveProcessLimitÚAffinityÚPriorityClassÚSchedulingClassr   N)rK   rL   rM   rN   ÚLARGE_INTEGERÚDWORDÚc_size_tÚPOINTERÚULONGr<  rP   )r>  r0  s   €€r   Ú!JOBOBJECT_BASIC_LIMIT_INFORMATIONrA  w  s‰   ø† à*©H×,BÑ,BÐCÐF[Ñ]e×]sÑ]sÐEtØ™xŸ~™~Ð.Ð1HÉ&Ï/É/Ð0ZØ(©&¯/©/Ð:Ð=QÑS[×SaÑSaÐ<bØ™VŸ^™^©H¯N©NÓ;Ð<¸ÑPX×P^ÑP^Ð>_Ø"¡H§N¡NÐ3ðŒHr   rP  c                  óD   <€ ] tR tRtR Z3R Z 3.V3R lR 4       OtRtR# )ÚNattach_self_to_kill_on_close_job.<locals>.JOBOBJECT_EXTENDED_LIMIT_INFORMATIONi€  ÚBasicLimitInformationÚIoInfoc              3  	ó>   <"  € T F  qSP                   3x € K  	  R # 5irÑ   )rM  )r  r=  r>  s   & €r   r  ÚXattach_self_to_kill_on_close_job.<locals>.JOBOBJECT_EXTENDED_LIMIT_INFORMATION.<genexpr>„  s#   øé € ð kñ 1j¨1�f—o‘oÕ&ó 1jùs   ƒr   N)ÚProcessMemoryLimitÚJobMemoryLimitÚPeakProcessMemoryUsedÚPeakJobMemoryUsed)rK   rL   rM   rN   r<  rP   )r?  rP  r>  s   €€€r   Ú$JOBOBJECT_EXTENDED_LIMIT_INFORMATIONrR  €  s2   ø† à(Ñ*KÐLØ™;Ð'ðôkñ 1jó kðŒHr   r[  Fz$attached to kill-on-close job objectzjob object self-attach failedrê   )r  Ú_JOB_HANDLEr>  r0  ÚWinDLLÚ	StructureÚCreateJobObjectWrS  rD  ÚSetInformationJobObjectÚbyrefÚsizeofÚAssignProcessToJobObjectÚGetCurrentProcessÚCloseHandler“   rî   r    )r1  Ú"JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSEÚJOB_OBJECT_LIMIT_BREAKAWAY_OKÚ$JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OKÚ!JobObjectExtendedLimitInformationr[  Újobr  Úokr?  rP  r>  r0  s            @@@@r   Ú attach_self_to_kill_on_close_jobrl  ^  sb  û€ ÷ ‹;œ+Ò1Ü $Ð&Ð&ð1ÛÝ#à—=‘= ¸D�=ÓAˆà-3Ð*Ø(.Ð%Ø/5Ð,Ø,-Ð)÷	R˜&×*Ñ*ô 	R÷
	ð 	°×0@Ñ0@ô 	÷	ñ 	°6×3CÑ3Cô 	ð ×'Ñ'¨¨dÓ3ˆßÙÙ3Ó5ˆà.ÕNÐQuÕuð 	×"Ñ"Ô-ð ×-Ñ-¨cÐV\×VbÑVbÐcgÓVhÐjp×jwÑjwÐx|Ój}Ó~ˆß˜×:Ñ:¸3×@ZÑ@ZÓ@\×]Ò]Ø× Ñ  Ô%ÙØˆÜ�‰Ð;Ô<ÙøÜô Ü�‰Ð4¸tˆÔDÚðús   ¢B	E Â.BE ÅE Å"FÆF>   ÚserveÚgatewayÚ	dashboardr   rÑ   )IÚ__conditional_annotations__Ú__doc__Ú
__future__r   r&   r‡   Úloggingr@   Úplatformrµ   Ú	threadingrä   Ú
contextlibr   Úcontextvarsr   Údataclassesr   r   Úpathlibr   Útypingr   r	   r
   Úutilsr   Ú	getLoggerrK   r“   r]   rV   r{   Ú	frozensetÚREAPABLE_PURPOSESr  Úsystemr  r\  ÚLockrì   r,   r9   rB   rE   rY   r^   rk   rm   r}   rŽ   r—   rœ   r¨   rº   rÃ   rÆ   rO   rÍ   rÒ   rÚ   r³   r´   r¶   rô   rú   rþ   r  r  r  r#  r   rl  )rp  s   @r   Ú<module>r�     sì  øðôõ #ã Û Û Û 	Û Û 
Û Û Ý %Ý "ß )Ý ß /Ñ /å #à	×	Ò	˜8Ó	$€à€Ø€Ø%€ñ ÒMÓNÐ ð ,¨|¨nÕ<Ð à�oŠoÓ 9Ñ,€ð €Ø�~Š~Ó€÷Qõ %÷.ñ �$Ô÷$ð $ó ð$ðfÀD÷ fðP¸d÷ Põ
Hð& ÷ð ó ðõ(	9õ\õ*
õVð
ÐQV÷ ð, À$ð  Ðae÷  ÷BUñ, ,6Ð6TÐ^cÔ+dÐ Ð(Ó dð ô,ó ð,õ(õ:õ!õ&õð> ÈT÷  ð2Ø&*ðØAFðØ^c÷õ60õõ&ð.-Ø7;÷-ð`,Àð ,Èd÷ ,õd÷<:r   