+
    jHàjûO  ã                  ó  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
 ^ RIHt ]P                  ! ]4      tRtRtRtR	tR
tRtR R ltR R lt]! RR7       ! R R4      4       tR R ltR R ltR R ltR R ltR R ltRtRsR] R &   R! R" lt!R# R$ lt"R%R&/R' R( llt#R%R&/R) R* llt$R+R,R-R/R. R/ llt%]! RR7       ! R0 R14      4       t&R2 R3 lt'R4 R5 lt(R6 R7 lt)R8 R9 lt*R: R; lt+R< R= lt,R>R?/R@ RA llt-R# )Buv
  Is there ONE live host gateway, and does it already serve this profile?

Multiplex-only (Teknium ruling): exactly one MULTIPLEXING ``hermes gateway run`` per host, serving
every profile; standalone per-profile gateways coexist until that migration is forced (#109417).
The lifecycle verbs therefore answer a different question than they used to â€” not "does THIS home
hold a ``gateway.pid``?" but "is the host process live, and is this profile in its served set?" â€”
and when it is not, they ask that process to serve the profile instead of starting a second one.
Five outcomes, in order:

* ``ATTACH``       â€” a live host gateway already serves this profile. Nothing to start; exit 0.
* ``RESCAN``â†’ATTACH â€” it does not serve it yet: ask it to reconcile ``profiles/`` now (control
  socket ``rescan-profiles``) and attach once the answer includes us.
* ``REPLACE_HOST`` â€” ``--replace`` targets the host process when it serves this profile, whichever
  home launched it. An owner that has not published its served set yet is targeted too, but the
  ownership guard (``run._replace_target_belongs_to_other_profile``) can then only prove it from
  THIS home's pid record, so from another home the replace is refused (exit 1).
* ``REFUSE``       â€” a live MULTIPLEXING gateway exists and cannot be made to serve this profile.
  Never start a second one silently.
* ``START``        â€” no live owner, or the owner answers ``multiplex: False``: it is another
  profile's standalone gateway (the documented one-process-per-profile topology), not a
  multiplexer that excluded us, so this profile runs its own gateway beside it as it always did.

**The attach channel is the OWNER's control socket, never ours.** Ordering matters: the owner
publishes its rendezvous record when it claims its PID file and binds its control socket a moment
later (``gateway/run.py``: claim â†’ socket), so for a short window the record exists and the channel
does not. A reader that took "no socket" for "no owner" would start exactly the second gateway this
module prevents â€” but a reader that took the RECORD's word for the served set is worse: the
claim-time record is published before the process knows what it will serve, so a supervised unit
for a profile nobody serves would stand down forever. Hence the split:

* the record proves an OWNER exists (PID + createTime), and that alone never yields ATTACH;
* the served set comes ONLY from a live ``identify`` answer, waited for a bounded
  :data:`ATTACH_CHANNEL_WAIT_S`;
* owner present + served set unknown is a TRANSIENT verdict â€” do not start, do not park.

Nothing here depends on the *calling* process having started anything.
)ÚannotationsN)Ú	dataclass)ÚPath)ÚOptionalg      @g      Ð?ÚstartÚattachÚrefusezreplace-hostc               ó    € V ^8„  d   QhRRRR/# )é   ÚnameÚstrÚreturn© )Úformats   "Ú8/home/ubuntu/.hermes/hermes-agent/gateway/host_attach.pyÚ__annotate__r   <   s   € ÷ 3ñ 3�Sð 3˜Sñ 3ó    c                ó¦   €  ^ RI Hp T! T ;'       g    R4      #   \         d,    T ;'       g    RP                  4       P	                  4       u # i ; i)é    )Únormalize_profile_nameÚdefault)Úhermes_cli.profilesr   Ú	ExceptionÚstripÚlower)r   r   s   & r   Ú
_normalizer   <   sL   € ð3Ý>á% d×&7Ð&7¨iÓ8Ð8øÜô 3Ø×!Ð!˜	×(Ñ(Ó*×0Ñ0Ó2Ò2ð3ús   ‚ “ šA®AÁAc               ó    € V ^8„  d   QhRRRR/# )r
   Úhomeú
Path | strr   r   r   )r   s   "r   r   r   E   s   € ÷ ;ñ ; 
ð ;¨sñ ;r   c                óD   € ^ RI Hp V! \        V 4      4      ;'       g    R# )zQProfile a home belongs to; the root/default home is ``'default'`` (not ``None``).)Ú_profile_name_for_homer   )Úgateway.statusr    r   )r   r    s   & r   Úprofile_name_for_homer"   E   s   € å5á!¤$ t£*Ó-×:Ð:°Ð:r   T)Úfrozenc                  ó„   € ] tR t^Lt$ RtR]R&   R]R&   R]R&   RtR	]R
&   RtR	]R&   R R lt]	R R l4       t
R R ltRtR# )ÚHostGatewayzQThe one live host gateway: who it is, where it was launched from, what it serves.ÚintÚpidr   r   útuple[str, ...]ÚprofilesTÚboolÚserved_knownFÚ
standalonec               ó    € V ^8„  d   QhRRRR/# )r
   Úprofiler   r   r*   r   )r   s   "r   r   ÚHostGateway.__annotate__Z   s   € ÷ Cñ C˜cð C dñ Cr   c                	óÞ   a€ V P                   '       g   R # \        V4      o\        ;QJ d)    V3R lV P                   4       F  '       g   K   R# 	  R # ! V3R lV P                   4       4      # )Fc              3  ó@   <"  € T F  p\        V4      S8H  x € K  	  R # 5i©N)r   )Ú.0ÚpÚwanteds   & €r   Ú	<genexpr>Ú%HostGateway.serves.<locals>.<genexpr>^   s   øé € ÐB±M¨q”:˜a“= FÖ*³Mùs   ƒT)r+   r   Úanyr)   )Úselfr.   r5   s   &&@r   ÚservesÚHostGateway.servesZ   sM   ø€ Ø× × Ð ÙÜ˜GÓ$ˆß‹sÔB°D·M²MÓB�sŒsÐBŠsÐBˆsÔB°D·M²MÓBÓBÐBr   c               ó   € V ^8„  d   QhRR/# ©r
   r   r   r   )r   s   "r   r   r/   a   s   € ÷ 0ñ 0˜sñ 0r   c                	ó,   € \        V P                  4      # r2   )r"   r   )r9   s   &r   Úprofile_labelÚHostGateway.profile_label`   s   € ä$ T§Y¡YÓ/Ð/r   c               ó   € V ^8„  d   QhRR/# r=   r   )r   s   "r   r   r/   d   s   € ÷ `ñ `˜#ñ `r   c                	óÊ   € V P                   '       g   R pM/V P                  '       d   RP                  V P                  4      MRpRV P                   RV P                   RV R2# )z7not published yet (its control socket has not answered)z, ÚnothingzPID z (launched by profile 'z'; serves: Ú))r+   r)   Újoinr'   r?   )r9   Úserveds   & r   ÚdescribeÚHostGateway.described   sY   € Ø× × Ð ØN‰Fà15··°�T—Y‘Y˜tŸ}™}Ô-ÀIˆFØ�d—h‘h�ZÐ6°t×7IÑ7IÐ6JÈ+ÐV\ÐU]Ð]^Ð_Ð_r   r   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__r+   r,   r:   Úpropertyr?   rG   Ú__static_attributes__r   r   r   r%   r%   L   sS   ‡ á[à	ƒHØ
ƒJØÓð €L�$Óð €J�ÓõCð ô0ó ð0÷`ñ `r   r%   c               ó   € V ^8„  d   QhRR/# )r
   r   r   r   )r   s   "r   r   r   l   s   € ÷ añ a˜4ñ ar   c                ó~   € ^ RI Hp \        V RR4      '       d   \        V P                  4      # \        V! 4       4      # )u�   Home the owner was launched from. Records written before the field existed fall back to the
default root â€” the home every pre-record multiplexer ran under.©Úget_default_hermes_rootr   Ú )Úhermes_constantsrT   Úgetattrr   r   )ÚrecordrT   s   & r   Úrecord_homerY   l   s2   € õ 9ä '¨°¸× ;Ò ;Œ4�—‘ÓÐ`ÄÑF]ÓF_ÓA`Ð`r   c               ó$   € V ^8„  d   QhRRRRRR/# )r
   Ú
owner_homer   Úour_homer   r*   r   )r   s   "r   r   r   t   s&   € ÷ Iñ I¨ð I¸zð IÈdñ Ir   c                óŒ   € \        T ;'       g    R4      '       g   R# ^ RIHp ^ RIHp V! V! V R7      V! VR7      4      '       * # )a§  Was the owner launched from ANOTHER Hermes root (a second tenant on this host)?

The host record and lock are per OS user, and two tenants (separate ``HERMES_HOME`` roots)
each expose a profile named ``default``: tenant A's multiplexer "serving default" is a name
collision for tenant B, never coverage, so it is not this tenant's host gateway (#121352).
A legacy record with no ``home`` proves nothing and counts as ours.
rU   F©Ú_same_hermes_homerS   )r   )r   r!   r_   rV   rT   )r[   r\   r_   rT   s   &&  r   Úlaunched_by_other_tenantr`   t   sE   € ô ˆz×Ð˜R× Ò ÙÝ0Ý8á Ñ!8¸jÔ!IÙ!8¸hÔ!GóIô Ið Ir   c               ó    € V ^8„  d   QhRRRR/# )r
   r   r   r   zOptional[dict]r   )r   s   "r   r   r   …   s   € ÷ ñ �Dð ˜^ñ r   c                ót   €  ^ RI Hp V! V 4      #   \         d    \        P	                  RT RR7        R# i ; i)r   )Úidentify_gatewayz#host gateway identify failed for %sT©Úexc_infoN)Úgateway.control_socketrc   r   ÚloggerÚdebug)r   rc   s   & r   Ú	_identifyri   …   s:   € ðÝ;á Ó%Ð%øÜô Ü�‰Ð:¸DÈ4ˆÔPÚðús   ‚ �#7¶7c               ó    € V ^8„  d   QhRRRR/# )r
   ÚidentityÚdictr   r(   r   )r   s   "r   r   r   �   s   € ÷ 8ñ 8 Dð 8¨_ñ 8r   c                óè  € V P                  R4      p\        V\        4      '       d¨   V'       d    . pV FŒ  p\        V\        4      '       dZ   VP                  R4      ;'       g    VP                  R4      pTP	                  V'       d   \        \        V4      4      MR4       Kr  VP	                  \        V4      4       KŽ  	  \        V4      # \        V P                  R4      ;'       g    R4      3# )a¯  Served set from a live ``identify``. A STANDALONE gateway publishes no ``served_profiles``;
it serves its own profile and nothing else, which is not the same as "unknown".

The unified runtime publishes each served profile as ``{"profile_id", "home"}`` (what
``hermes_cli.gateway_runtime`` matches homes against); older gateways published bare names.
Both spell the same roster, so a dict entry is reduced to its profile name here.Úserved_profilesr   Ú
profile_idr   r.   )ÚgetÚ
isinstanceÚlistrl   Úappendr"   r   Útuple)rk   rF   ÚnamesÚentryr   s   &    r   Ú_served_from_identityrw   �   s²   € ð �\‰\Ð+Ó,€FÜ�&œ$×Ò§FØˆÛˆEÜ˜%¤×&Ò&Ø—y‘y Ó(×CÐC¨E¯I©I°lÓ,C�Ø—‘ÇÔ2´3°t³9Ô=È9ÖUà—‘œS ›ZÖ(ñ ô �U‹|ÐÜ�—‘˜YÓ'×4Ð4¨9Ó5Ð7Ð7r   c               ó    € V ^8„  d   QhRRRR/# )r
   r   r   r   r*   r   )r   s   "r   r   r   £   s   € ÷ *ñ *¨dð *°tñ *r   c           	     óN  € \        V \        4      '       d!   V P                  R4      VP                  8w  d   R# V P                  R4      pV'       g   R#  ^ RIHp \        V! \        \        V4      4      V4      4      #   \         d    \        T4      \        T4      8H  u # i ; i)zÜIs this ``identify`` answer really the record's owner?

PID alone is not enough: a record naming an arbitrary home makes us dial whatever listens
there, so the answer must also agree about the home it was launched from.
r'   FÚhermes_homeTr^   )
rq   rl   rp   r'   r!   r_   r*   r   r   r   )rk   rX   r   Úreportedr_   s   &&&  r   Ú_identity_matchesr|   £   s‚   € ô �h¤×%Ò%¨¯©°eÓ)<ÀÇ
Á
Ô)JÙØ�|‰|˜MÓ*€HßÙð*Ý4äÑ%¤d¬3¨x«=Ó&9¸4Ó@ÓAÐAøÜô *Ü�8‹}¤ D£	Ñ)Ò)ð*ús   Á)A? Á?"B$Â#B$g       @z-Optional[tuple[float, Optional[HostGateway]]]Ú_cached_probec               ó   € V ^8„  d   QhRR/# )r
   r   ÚNoner   )r   s   "r   r   r   ½   s   € ÷ ñ  tñ r   c                 ó
   € Rs R# )zPForget the memoized probe (called by ``host_rendezvous`` on every record write).N)r}   r   r   r   Úinvalidate_host_gateway_cacher�   ½   s	   € ð ‚Mr   c               ó    € V ^8„  d   QhRRRR/# ©r
   Úwait_for_channelÚfloatr   úOptional[HostGateway]r   )r   s   "r   r   r   Ã   s   € ÷ Añ A¨%ð AÐ4Iñ Ar   c                ó   € ^ RI Hp VP                  VP                  4      pVf   R# VP	                  V4      '       g   R# \        V4      p\        P                  ! 4       \        RV 4      ,           p \        V4      p\        WRV4      '       d!   \        VP                  V\        V4      4      # \        P                  ! 4       V8¼  d   M\        P                  ! \        4       Ku  \        VP                  VRRR7      # )r   )Úhost_rendezvousNç        F©r+   r   )Úgatewayrˆ   Úread_recordÚROLE_GATEWAYÚrecord_names_live_ownerrY   ÚtimeÚ	monotonicÚmaxri   r|   r%   r'   rw   ÚsleepÚ_CHANNEL_POLL_S)r„   ÚhrrX   r   Údeadlinerk   s   &     r   Ú_probe_host_gatewayr–   Ã   s½   € Ý-à�^‰^˜BŸO™OÓ,€FØ‚~Ùð
 ×%Ñ% f×-Ò-ÙÜ�vÓ€DÜ�~Š~Ó¤# cÐ+;Ó"<Õ<€HØ
Ü˜T“?ˆÜ˜X¨t×4Ò4Ü˜vŸz™z¨4Ô1FÀxÓ1PÓQÐQÜ�>Š>Ó˜xÔ'ØÜ�
Š
”?Ö#ä�v—z‘z 4¨¸%Ô@Ð@r   r„   r‰   c               ó    € V ^8„  d   QhRRRR/# rƒ   r   )r   s   "r   r   r   Ü   s   € ÷ ñ  eð Ð6Kñ r   c                óæ   € \         P                  ! 4       pV ^ 8:  d3   \        e+   V\        ^ ,          ,
          \        8  d   \        ^,          # \	        V 4      p\         P                  ! 4       V3sV# )uå   The one live host gateway, or ``None``.

The served set comes from the owner's control socket and nowhere else; a record with no live
answer behind it yields ``served_known=False`` â€” an owner whose served set nobody knows yet.
)r�   r�   r}   ÚHOST_GATEWAY_CACHE_TTL_Sr–   )r„   ÚnowÚresults   $  r   Úhost_gatewayrœ   Ü   s\   € ô �.Š.Ó
€CØ˜1Ô¤Ò!:¸sÄ]ÐSTÕEUÕ?UÔXpÔ?pÜ˜QÕÐÜ Ð!1Ó2€FÜ—^’^Ó% vÐ.€MØ€Mr   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'   € ÷ Pñ P #ð P¸Eð PÐLañ Pr   c               óX   € \        VR7      pVe   VP                  V 4      '       d   V# R# )uU   The host gateway when it is live AND serves ``profile`` â€” true for ``default`` too.©r„   N)rœ   r:   )r.   r„   r‹   s   &$ r   Úhost_gateway_servingr    ë   s+   € äÐ,<Ô=€GØÒ)¨g¯n©n¸W×.EÒ.Eˆ7ÐOÈ4ÐOr   Útimeoutg       @Úownerc               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   r.   r   r¡   r…   r¢   r†   r   r   )r   s   "r   r   r   ñ   s0   € ÷ Tñ T 3ð T°Eð TØ!6ðTØBWñTr   c               óˆ  € Ve   TM\        \        R7      pVe   VP                  V 4      '       d   V#  ^ RIHp V! VP
                  VR7      p\        T\        4      '       g   R# TP                  R4      p\        TP                  TP
                  \        T\        4      '       d-   \        ;QJ d    . R	 T 4       F  NK  	  5M! R	 T 4       4      MRTP                  R
4      RJ R7      pTP                   '       g   TP                  T 4      '       d   T# R#   \         d    \        P                  RRR7        R# i ; i)up  Ask the live host gateway to reconcile ``profiles/`` now; return it once it serves
``profile``. ``None`` when nobody answered or a multiplexer's roster still excludes the profile.
An owner that answers ``multiplex: False`` comes back flagged ``standalone``: it cannot take the
profile, and it is not a multiplexer that refused â€” the caller runs beside it, as before.NrŸ   )Úrescan_gateway_profiles)r¡   zhost gateway rescan failedTrd   rn   c              3  ó8   "  € T F  p\        V4      x € K  	  R # 5ir2   )r   )r3   r4   s   & r   r6   Ú(request_serve_profile.<locals>.<genexpr>  s   é € Ð%™f˜Œc�!�fˆf›fùs   ‚Ú	multiplexF©r,   r   )rœ   ÚATTACH_CHANNEL_WAIT_Sr:   rf   r¥   r   r   rg   rh   rq   rl   rp   r%   r'   rr   rt   r,   )r.   r¡   r¢   r‹   r¥   ÚanswerrF   Ú	rescanneds   &$$     r   Úrequest_serve_profiler­   ñ   s  € ð Ò(‰e¬lÔLaÔ.b€GØ‚˜'Ÿ.™.¨×1Ò1ØˆðÝBá(¨¯©¸wÔGˆô �fœd×#Ò#ÙØ�Z‰ZÐ)Ó*€FÜØ�‰�W—\‘\Ü)3°F¼D×)AÒ)A�ŒÑ%™fÓ%�‰Ñ%™fÓ%Ô%ÀrØ—:‘:˜kÓ*¨eÐ3ô5€Ið "×,×,Ð,°	×0@Ñ0@À×0IÒ0Iˆ9ÐSÈtÐSøô ô Ü�‰Ð1¸DˆÔAÚðús   µD Ä"EÅ Ec                  óH   € ] tR tRt$ R]R&   R]R&   RtR]R&   RtR	]R
&   RtR# )ÚHostAttachDecisioni  r   ÚoutcomeÚmessageNr†   r¢   Fr*   Ú	transientr   )rI   rJ   rK   rL   rN   r¢   r²   rP   r   r   r   r¯   r¯     s#   ‡ àƒLØƒLØ#'€EÐ Ó'ð €Iˆt×r   r¯   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&   € ÷ Añ A˜Kð A°#ð A¸#ñ Ar   c                óJ   € R V RV P                  4        RV P                   R2# )u-   âœ“ The host gateway already serves profile 'u   ' â€” nothing to start.
  zH
  One gateway per host serves every profile; manage it with `hermes -p z gateway restart`.)rG   r?   ©r‹   r.   s   &&r   Úattach_messager·     s>   € à
7¸°yð AØ×ÑÓÐ ð !à×+Ñ+Ð,Ð,>ð	@ðAr   c               ó$   € V ^8„  d   QhRRRRRR/# r´   r   )r   s   "r   r   r     s!   € ÷ 9ñ 9 [ð 9¸3ð 9À3ñ 9r   c                ó0   € R V P                  4        RV R2# )uR   â�³ A gateway already owns this host and has not published its served set yet.
   z#
   Whether it will serve profile 'a<  ' is unknown, so starting a second gateway
   now could double-bind this profile's platforms. Nothing was started; this is a
   transient state and a service supervisor will retry.
   Take the host over (only from the home that launched it):  hermes gateway run --replace
   Start anyway:  hermes gateway run --force)rG   r¶   s   &&r   Ú_unknown_served_messagerº     s/   € ðØ×ÑÓ Ð!ð "-Ø-4¨Ið 67ð	8ð9r   c               ó$   € V ^8„  d   QhRRRRRR/# r´   r   )r   s   "r   r   r   )  s&   € ÷ 
pñ 
p˜[ð 
p°3ð 
p¸3ñ 
pr   c                óB   € ^ RI Hp RV RV P                  4        RV R2# )r   ©ÚMIGRATE_COMMANDuA   â�Œ A gateway already owns this host and will not serve profile 'z'.
   zŸ
   Exactly one gateway per host serves every profile, so starting a second one
   would double-bind this profile's platforms.
   Fold this profile into it:   zŸ
   Or start one anyway:         hermes gateway run --force
   (--replace only replaces an owner that serves this profile, so it would not take this one over.))Úhermes_cli.gateway_migrater¾   rG   )r‹   r.   r¾   s   && r   Ú_refuse_messagerÀ   )  sC   € Ý:ð LÈGÈ9ð UØ×ÑÓ Ð!ð "+ð ,;Ð*;ð <nð		oðpr   c               ó    € V ^8„  d   QhRRRR/# )r
   r.   r   r   r   )r   s   "r   r   r   6  s   € ÷ Gñ G sð G¨sñ Gr   c                ó   € R V  R2# )z'The host gateway still serves profile 'z¸'; gateway.standalone is not live yet. Wait for the host gateway to rescan (<=30s), or send the rescan-profiles control verb to the host gateway before starting this profile's gateway.r   )r.   s   &r   Ústandalone_rescan_messagerÃ   6  s   € à
1°'°ð ;Fð 	FðGr   c               ó   € V ^8„  d   QhRR/# )r
   r¢   r†   r   )r   s   "r   r   r   =  s   € ÷ ñ Ð 5ñ r   c           	   #  óä  "  € ^ RI Hp ^ RIHp \        P
                  ! 4       0pV e    VP                  V P                  4       V x € V! RRRR7       F—  w  rEV! V4      pVe   Wc9   d   K  VP                  V4       \        WeR
RR7      p\        V4      p\        V\        4      '       d;   \        W‡V4      '       d)   \        We\        V4      VP                  R4      RJ R	7      pVx € K™  	  R# 5i)z×A standalone lock owner can hide a multiplexer launched beside it.

Use the existing per-home liveness and control channels, not the single host
record, to ask every running profile gateway what it actually serves.
)Úlive_gateway_pid_for_home)Úprofiles_to_serveNT)Úinclude_standaloneÚinclude_parkedFrŠ   r¨   r©   r   )r!   rÆ   r   rÇ   ÚosÚgetpidÚaddr'   r%   ri   rq   rl   r|   rw   rp   )	r¢   rÆ   rÇ   ÚseenÚ_namer   r'   Úpeerrk   s	   &        r   Ú_coexisting_gatewaysrÐ   =  sÉ   é € õ 9Ý5ä�IŠI‹Kˆ=€DØÒØ�‰�—‘ÔØŠÙ(¨À$ÐW[×\‰ˆÙ'¨Ó-ˆØŠ;˜#œ+ÙØ�‰�ŒÜ˜3 b°uÔ=ˆÜ˜T“?ˆÜ�h¤×%Ò%Ô*;¸HÈD×*QÒ*QÜ˜sÔ*?ÀÓ*IØ*2¯,©,°{Ó*CÀuÐ*LôNˆDàŒ
ó ]ùs   ‚C.C0c               ó$   € V ^8„  d   QhRRRRRR/# )r
   r\   r   r¢   r†   r   zOptional[HostAttachDecision]r   )r   s   "r   r   r   W  s#   € ÷ 0ñ 0¨ð 0Ð6Kð 0ÐPlñ 0r   c                ó€  € ^ RI Hp V! V 4      '       g   R# \        V 4      p\        V4       Fh  pVP                  '       g   \        \        \        WC4      VRR7      u # VP                  V4      '       g   KL  \        \        \        V4      VRR7      u # 	  \        P                  RV4       \        \        RV4      # )z›An opt-out permits coexistence only after every live gateway confirms we are unserved.

Shared by the initial attach check and the lock-losing race check.
)Úprofile_is_standaloneNT©r²   zJProfile '%s' is standalone by config; starting beside the host multiplexerrU   )r   rÓ   r"   rÐ   r+   r¯   ÚREFUSErº   r:   rÃ   rg   ÚinfoÚSTART)r\   r¢   rÓ   r.   rÏ   s   &&   r   Ústandalone_attach_decisionrØ   W  sœ   € õ
 :á  ×*Ò*ÙÜ# HÓ-€GÜ$ UÖ+ˆØ× × Ð Ü%¤fÔ.EÀdÓ.TÐVZÐfjÔkÒkØ�;‰;�w×ÔÜ%¤fÔ.GÈÓ.PÐRVÐbfÔgÒgñ	 ,ô
 ‡K�KÐ\Ð^eÔfÜœe R¨Ó/Ð/r   ÚreplaceFc               ó$   € V ^8„  d   QhRRRRRR/# )r
   r\   r   rÙ   r*   r   r¯   r   )r   s   "r   r   r   j  s'   € ÷ >Rñ >R�Tð >R tð >RÐ8Jñ >Rr   c               ó¦  € \        V 4      p \        4       pTeA   TP                  \        P                  ! 4       8X  g   \        TP                  T 4      '       d%   \        T R4      ;'       g    \        \        R4      # T'       d;   TP                  T4      '       g   TP                  '       g   \        \        RT4      # TP                  '       d   \        Y4      pTe   T# TP                  T4      '       d   \        \         \#        Y24      TRR7      # TP                  '       gk   \        \$        R7      pTf   \        \        R4      # Tp\        Y4      pTe   T# TP                  T4      '       d   \        \         \#        Y24      TRR7      #  \'        Y#R7      pTe4   TP                  T4      '       d   \        \         \#        Yb4      TRR7      # TeN   TP(                  '       d<   ^ R
IHp \        P/                  RTP1                  4       Y'4       \        \        R4      # TP                  '       g   \        \2        \5        Y24      TRR7      # \        \2        \7        Y24      T4      #   \         d+    \        P	                  RRR7       \        \        R4      u # i ; i  \         d    \        P	                  R	RR7       Rp EL/i ; i)z»Attach, rescan-then-attach, replace or refuse; configured standalone profiles may coexist.

Never raises: a broken probe degrades to ``START``, i.e. exactly the pre-rendezvous behaviour.
z-host gateway probe failed; starting as beforeTrd   rU   NrÔ   rŸ   )r¢   z"host gateway rescan request failedr½   z‡Another profile's standalone gateway owns this host (%s); starting profile '%s' beside it. Fold every profile onto one gateway with: %s)r"   rœ   r   rg   rh   r¯   r×   r'   rÊ   rË   r`   r   rØ   r:   r+   ÚREPLACE_HOSTÚATTACHr·   rª   r­   r,   r¿   r¾   rÖ   rG   rÕ   rº   rÀ   )r\   rÙ   r.   r‹   r,   ÚwaitedÚattachedr¾   s   &$      r   Údeciderà   j  s_  € ô
 $ HÓ-€Gð-Ü“.ˆð ‚˜'Ÿ+™+¬¯ª«Ô4Ô8PÐQX×Q]ÑQ]Ð_g×8hÒ8hÜ)¨(°DÓ9×ZÐZÔ=OÔPUÐWYÓ=ZÐZß�G—N‘N 7×+Ò+°7×3G×3GÐ3Gô
 "¤,°°GÓ<Ð<Ø××ÐÜ/°ÓBˆ
ØÒ!ØÐØ‡~�~�g×ÒÜ!¤&¬.¸Ó*JÈGÐ_cÔdÐdØ××Ðô Ô/DÔEˆØŠ>Ü%¤e¨RÓ0Ð0ØˆÜ/°ÓBˆ
ØÒ!ØÐØ�>‰>˜'×"Ò"Ü%¤f¬n¸WÓ.NÐPWÐcgÔhÐhðÜ(¨Ô@ˆð Ò §¡°× 8Ò 8Ü!¤&¬.¸Ó*KÈXÐaeÔfÐfØÒ × 3× 3Ð 3õ 	?ä�‰ð;à×ÑÓ ô	;ô "¤%¨Ó,Ð,Ø××Ðô "ÜÔ+¨GÓ=¸wÐRVôXð 	Xäœf¤o°gÓ&GÈÓQÐQøôm ô -Ü�‰ÐDÈtˆÔTÜ!¤%¨Ó,Ò,ð-ûô> ô Ü�‰Ð9ÀDˆÔIØ‹ðús#   �
I0 ÆJ( É02J%Ê$J%Ê($KËK).Ú__conditional_annotations__rM   Ú
__future__r   ÚloggingrÊ   r�   Údataclassesr   Úpathlibr   Útypingr   Ú	getLoggerrI   rg   rª   r“   r×   rÝ   rÕ   rÜ   r   r"   r%   rY   r`   ri   rw   r|   r™   r}   rN   r�   r–   rœ   r    r­   r¯   r·   rº   rÀ   rÃ   rÐ   rØ   rà   )rá   s   @r   Ú<module>rè      s<  øðô$õL #ã Û 	Û Ý !Ý Ý à	×	Ò	˜8Ó	$€ð Ð Ø€à€Ø	€Ø	€Ø€õ3õ;ñ �$Ô÷`ð `ó ð`õ>aõIõ"õ8õ(*ð, Ð Ø?C€Ð<Ó CõõAð2¨c÷ ðPÀC÷ PðT¸Cð TØ9=÷Tñ4 �$Ô÷ð ó ðõAõ9õ
põGõõ40ð&>R¨e÷ >Rñ >Rr   