+
    „WÝjí<  ã                   ó˜   € R t ^ RIt^ RIt^ RIHtHtHt RtRtRt	R t
RR ltR tR	 tR
 tR tR tR tR tR tR tR tR tR tR tR# )zKPrivate local creation receipts in the canonical runtime transaction owner.N)ÚRuntimeStoreErrorÚ_epochÚ_jsonzgateway.local_policy.v1:zgateway.api.binding.v1.zgateway.api.conversation.v1.c          	     óÐ  a aaaaaaaa	€ \        SRR4      o\        SRR4      oSf(   SR,          P                  R4      e   \        R4      h/ oSe   SP                  4        \	        S4      o\
        P                  ! S4      oSR,          SR,          uo	o\        S	,           oV VVVVVVVV	3	R	 lp S P                  V4      #   \         d    Se   SP                  4        h i ; i)
a  Reserve the row, route and immutable policy together, before publication. A staged receipt's
``on_create`` (owner memory, never stored) is published by the transaction that creates the row
and withdrawn if that transaction fails: an exact retry, a refused or a losing attempt adds none.Ú	on_createNÚclient_requestÚpolicyÚclient_env_jsonÚinvalid_paramsÚ
session_idÚroutec                 óv  <	a€ \        V S4       V P                  R S34      P                  4       pVeœ    \        P                  ! V^ ,          4      o\
        ;QJ d     VV3R lR 4       F  '       d   K   RM	  RM! VV3R lR 4       4      pT;'       d#    \        SR,          SR,          R,          S4      pT'       g   \        R	4      hS# ^ R
IHp V P                  RVS,           34      P                  4       '       d   \        R4      hRS9  d3   V P                  RS34      P                  4       '       d   \        R4      hV P                  RS34      P                  4       '       d   \        R4      hRS9   d   ^ RIHp V! SV S4       SR,          SR,          rv^ RIHp VP!                  VR,          4      P#                  4       p	^ RIHp
 V
! VR,          4      pV P                  RSVR,          VSR,          SVR,          R,          VR,          \)        V4      SP+                  4       \-        VR,          4      V	34       V P                  RS\-        V4      V	34       V P                  RSS34       Se   SP/                  4        S#   \        \        \        3 d   p\        R4      ThRp?ii ; i)ú(SELECT value FROM state_meta WHERE key=?Nc              3   óJ   <"  € T F  pSV,          SV,          8H  x € K  	  R # 5i©N© )Ú.0ÚkÚreceiptÚsaveds   & €€ÚFC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_state_local.pyÚ	<genexpr>Ú6commit_local_session.<locals>.write.<locals>.<genexpr>#   s)   øé € ð Xñ <W°a˜5 �8 w¨q¥zÖ1ó <Wùs   ƒ #Úprincipal_idFTr   Úrequest_jsonÚstorage_unavailabler
   )ÚRETIRED_PREFIXz$SELECT 1 FROM state_meta WHERE key=?Ú	not_foundÚlegacy_session_idz!SELECT 1 FROM sessions WHERE id=?z>SELECT 1 FROM gateway_routing WHERE scope='' AND session_key=?Úadmission_conflict)Úbind_legacy_targetÚentry)ÚdatetimeÚ
created_at)Úcreated_surfaceÚsourcezÙINSERT INTO sessions(id,source,created_source,user_id,session_key,chat_id,chat_type,
            model,cwd,profile_name,origin_json,started_at) VALUES(?,?,?,?,?,?,'dm',?,?,?,?,?)
            ON CONFLICT(id) DO NOTHINGÚoriginÚchat_idÚmodelzUINSERT INTO gateway_routing(scope,session_key,entry_json,updated_at) VALUES('',?,?,?)z-INSERT INTO state_meta(key,value) VALUES(?,?))Ú
profile_idr   Ú
request_idr   r   )r   ÚexecuteÚfetchoneÚjsonÚloadsÚallÚsame_create_retryÚ
ValueErrorÚ	TypeErrorÚKeyErrorr   Ú hermes_state_mutation_retirementr   Úhermes_state_local_migrationr    r"   ÚfromisoformatÚ	timestampÚgateway.session_policyr$   Ú_row_cwdÚ_own_profile_namer   Úpublish)ÚconnÚoldÚsameÚexcr   r    r   r!   r"   Ústartedr$   Úcreatedr   ÚdbÚencodedÚepochÚkeyr   r   Úrequestr   Úsids   &           @€€€€€€€€€r   ÚwriteÚ#commit_local_session.<locals>.write   sy  ù€ Üˆt�UÔØ�l‰lÐEÈÀvÓN×WÑWÓYˆØŠ?ðHÜŸ
š
 3 q¥6Ó*�ß“sõ Xñ <Wó X—s—s’sõ Xñ <Wó Xó X�à×nÐnÔ 1°%¸µ/À7È8ÕCTÐUcÕCdÐfmÓ n�÷ Ü'Ð(8Ó9Ð9ØˆLÝCØ�<‰<Ð>ÀÐRUÕAUÐ@WÓX×aÑa×cÒcô $ KÓ0Ð0Ø wÔ.Ø—‘Ð@À3À&ÓI×RÑR×TÒTÜ#Ð$9Ó:Ð:Ø�<‰<ÐXÐ[`ÐZbÓc×lÑl×nÒnÜ#Ð$8Ó9Ð9Ø 'Ô)ÝGÙ˜r 4¨Ô1Ø Õ)¨7°7Õ+;�Ý%Ø×(Ñ(¨¨|Õ)<Ó=×GÑGÓIˆõ 	;Ù! &¨Õ"2Ó3ˆØ�‰ð *ð �&˜Õ" G¨W°^Õ-DÀeØ�8�_˜YÕ'¨°­¼(À6Ó:JÈB×L`ÑL`ÓLbÜ�5˜•?Ó# Wð.ô	/ð 	�‰ÐlØœU 5›\¨7Ð3ô	5à�‰ÐDÀsÈGÀnÔUØÒ Ø×ÑÔØˆøôQ ¤	¬8Ð4ô HÜ'Ð(=Ó>ÀCÐGûðHús)   µ'J ÁJ Á5!J Â#J ÊJ8Ê'J3Ê3J8)ÚgetattrÚgetr   Úreadr   r-   r.   ÚPOLICY_PREFIXÚ_execute_writeÚBaseExceptionÚwithdraw)
rB   rD   r   rH   rC   rE   r   rF   r   rG   s
   fdd @@@@@@r   Úcommit_local_sessionrQ      sÛ   ÿø€ ô ˜ ¨dÓ3€IÜ�gÐ/°Ó6€GØ‚Ø�8Õ× Ñ Ð!2Ó3Ò?ä#Ð$4Ó5Ð5ØˆØÒØ�‰ÔÜ�G‹n€GÜ�jŠj˜Ó!€GØ˜Õ&¨°Õ(8€J€CˆÜ
˜#Õ
€C÷1õ 1ðdØ× Ñ  Ó'Ð'øÜô ØÒ Ø×ÑÔ Øðús   Â3C Ã!C%c                óö   € \         P                  ! V 4      pVP                  RR4       Vf   VP                  RR4       RV9   d4   VP                  RR4       Vf   RMT F  pVP                  VR4       K  	  V# )a�  A frozen create request as the client sent it: an owner-resolved ``-m`` route (``model_requested``)
compares by the name the client typed, not by the model and the *derived* fields (a receipt from
before ``route_derived``: the endpoint) its ``${VAR}`` refs expanded to at the time. ``desktop_local``
(``gateway.session_policy.LOCAL_DESKTOP_CHAT``), which an earlier owner stamped into the request, was
never sent.Údesktop_localNÚroute_derivedÚmodel_requestedr(   )Úbase_url)r-   r.   Úpop)r   ÚderivedrF   rE   s   &&  r   r   r   W   sp   € ô �jŠj˜Ó&€GØ‡K�K� Ô&Ø‚Ø�‰�O TÔ*Ø˜GÔ#Ø�‰�G˜TÔ"Ø$+¢O‘=¸Ò@ˆCØ�K‰K˜˜TÖ"ñ Aà€Nó    c                ór  € \         P                  ! V 4      P                  R4      p\        W4      \        W4      8X  d   R# \         P                  ! V4      pVP                  R4      VP                  R4      8X  d%   VP	                  RR4       VP	                  RR4       \         P                  ! V 4      V8H  # )a"  Whether a create retry carries the frozen request it resumes: one check for a retry that finds the
session committed and one staged before it was. The saved receipt's provenance names the owner's
fields; one from before a same-name alias got ``model_requested`` compares exactly, as it did.rT   TrU   r(   N)r-   r.   rK   r   rW   )Ú
saved_jsonÚ
retry_jsonrX   Úretrys   &&  r   Úsame_create_requestr^   h   sŒ   € ô �jŠj˜Ó$×(Ñ(¨Ó9€GÜ�jÓ*¬n¸ZÓ.QÔQÙÜ�JŠJ�zÓ"€EØ‡y�yÐ"Ó# u§y¡y°Ó'9Ô9Ø�	‰	Ð# TÔ*Ø�	‰	�/ 4Ô(Ü�:Š:�jÓ! UÑ*Ð*rY   c                óT   € ^ RI Hp \        V R,          V4      ;'       d	    V! W4      # )aX  The one exact-retry identity of a create: ``same_create_request`` on what the client sent, and its
``client_env`` (``client_request``: the retry's own, never stored) judged by the rules frozen with
*saved_policy*. Used by a retry that finds the session committed, at commit, and by one overlapping
the attempt that holds the session's key slot.)Úretry_matchesr   )Úagent.session_client_envr`   r^   )Úsaved_policyr\   r   r`   s   &&& r   r0   r0   v   s'   € õ
 7Ü˜|¨NÕ;¸ZÓH×xÐxÉ]Ð[gÓMxÐxrY   c                ó<  €  \         P                  ! V P                  R4      ;'       g    R4      p\        V\        4      '       d   VP                  R4      MRp\        V\        4      '       g
   V R,          # T;'       g    R#   \        \        3 d    / p Lii ; i)a  The sessions-row ``cwd``: the create request's ``row_cwd`` (``""`` = none) when it sent one,
else the execution cwd. Row metadata only (workspace grouping, ``-c``, cwd restore); the
frozen policy's ``cwd`` / ``TERMINAL_CWD`` stay where the session's tools run.r   z{}Úrow_cwdNÚcwd)r-   r.   rK   r2   r1   Ú
isinstanceÚdictÚstr)r   rF   Úvalues   &  r   r9   r9      s€   € ðÜ—*’*˜VŸZ™Z¨Ó7×?Ð?¸4Ó@ˆô '1°¼$×&?Ò&?ˆG�K‰K˜	Ô"ÀT€EÜ *¨5´#× 6Ò 6ˆ6�%�=ÐK¸U¿]¸]ÀdÐKøô ”zÐ"ô ØŠðús   ‚'B ªB ÂBÂBc                ó  €  \         P                  ! V 4      p\	        T\
        4      '       d   TP                  R4      MRp\	        T\
        4      '       d   TP                  R4      # R#   \        \        3 d     R# i ; i)zÖCurrent physical target a creation receipt routes to; None for a malformed receipt, which
then stays (its own reads already refuse it as ``storage_unavailable``) and cannot abort
the delete of an unrelated session.Nr!   r   )r-   r.   r2   r1   rf   rg   rK   )Úrawri   r!   s   &  r   Ú_policy_targetrl   ‹   sk   € ðÜ—
’
˜3“ˆô #-¨U´D×"9Ò"9ˆE�I‰I�gÔ¸t€EÜ&0°¼×&=Ò&=ˆ5�9‰9�\Ó"ÐGÀ4ÐGøô ”zÐ"ô Úðús   ‚A* Á*A?Á>A?c                óì  € \        V4      pV'       g   R# V P                  R\        R,           34       UUu. uF  w  r4\        V4      V9   g   K  VNK  	  pppYPP                  R\        R,           34       UUu. uF  w  r4WB9   g   K  VNK  	  upp,          pYR Uu. uF  p\
        V,           NK  	  up,          pT P                  RV Uu. uF  q33NK  	  up4       R# u uppi u uppi u upi u upi )a·  Deletion fence half for owner receipts. A local creation policy carries the launch request
(``request_json``: a cron fire's job and raw prompt), so it goes exactly when its route does:
when the receipt's current physical target is deleted (a pruned reset ancestor whose logical
session lives on in a child keeps it). An API binding and the declared conversation key that
resolves to it go with their id, so that key starts a fresh session.Nz1SELECT key,value FROM state_meta WHERE key GLOB ?Ú*z"DELETE FROM state_meta WHERE key=?)Úsetr+   rM   rl   ÚAPI_DECLARED_PREFIXÚAPI_BINDING_PREFIXÚexecutemany)r<   Úsession_idsÚtargetsrE   ri   ÚgonerG   s   &&     r   Úretire_local_receiptsrv   —   s  € ô �+Ó€GßÙà"&§,¡,Ð/bÜ0=ÀÕ0CÐ/Eô#Gô 1ñ #G‘J�Cä˜eÓ$¨Ñ/÷ ˆCñ #G€Dñ 1ð 	§<¡<Ð0cÜ1DÀsÕ1JÐ0Lô$Nô cñ $N‘Z�SØQVÑQa÷ ˆSñ $Nò cõ c€Dà°Ó9±¨#Ô #×%Ð%±Ñ9Õ9€DØ×ÑÐ9ÉdÓ;SÉdÀs»FÉdÑ;SÖTùó1ùócùâ9ùÚ;Ss#   ·C ÁC Á:
C&Â	C&ÂC,ÃC1
c                óÌ  € V P                  RV34      P                  4       pV'       d
   V^ ,          MRpV'       d   W18X  d   V# V P                  R\        V,           34      P                  4       p V'       d-   \        P                  ! V^ ,          4      P                  R4      MRp\        T\        4      '       d	   Y9   d   T# T#   \        \        \        3 d    Tu # i ; i)z°The creation id whose receipt lineage holds physical segment *session_id* (a reset or
compression child, which carries the owner as ``chat_id``); *session_id* itself otherwise.z'SELECT chat_id FROM sessions WHERE id=?Nr   Úlineage)r+   r,   rM   r-   r.   rK   r2   r1   ÚAttributeErrorrf   Úlist)r<   r   ÚrowÚownerr   rx   s   &&    r   Úlocal_lineage_ownerr}   ª   sÀ   € ð �,‰,Ð@À:À-Ó
P×
YÑ
YÓ
[€CßˆC�ŽF˜t€Eß�EÔ'ØÐØ�L‰LÐCÄmÐV[ÕF[ÐE]Ó^×gÑgÓi€Eðß9>”$—*’*˜U 1�XÓ&×*Ñ*¨9Ô5ÀDˆô ˜w¬×-Ò-°*Ô2Gˆ5ÐWÈZÐWøô ”z¤>Ð2ô ØÒðús   Á2C Á:.C ÃC#Ã"C#c           	     óV   € \        \        P                  V.\        W4      O4      4      # )aa  [session_id] for any row outside a local reset/compression lineage, else the whole
conversation (*session_id* first). Any segment deletes as all of it: the owner's policy goes
with its current target, and an earlier segment's gap breaks the lineage, so a lone segment
delete strands the rest (and the owner's queued work) readable but never continuable.)rz   rg   ÚfromkeysÚlocal_conversation_ids)r<   r   s   &&r   Úowned_lineage_idsr�   ¹   s&   € ô
 ”—‘˜zÐUÔ,BÀ4Ó,TÐUÓVÓWÐWrY   c                óœ  € \        W4      pV P                  R\        V,           34      P                  4       p V'       d-   \        P
                  ! V^ ,          4      P                  R4      MRp\        V\        4      '       g   V.# \        \        P                  V.R V 4       O4      4      #   \        \        \        3 d    Rp L[i ; i)a  Every row of the local conversation *session_id* belongs to: its creation id first, then
each segment of the receipt lineage. A canonical reset never forks the logical session (one
policy, FIFO and generation), so listing, delete and retirement treat these ids as one.r   rx   Nc              3   óV   "  € T F  p\        V\        4      '       g   K  Vx € K!  	  R # 5ir   ©rf   rh   ©r   rG   s   & r   r   Ú)local_conversation_ids.<locals>.<genexpr>Í   s   é € Ð'W±w°Ä*ÈSÔRU×BV¯ª³wùs   ‚)Ÿ
))r}   r+   rM   r,   r-   r.   rK   r2   r1   ry   rf   rz   rg   r   )r<   r   r|   r   rx   s   &&   r   r€   r€   Á   s­   € ô   Ó1€EØ�L‰LÐCÄmÐV[ÕF[ÐE]Ó^×gÑgÓi€Eðß9>”$—*’*˜U 1�XÓ&×*Ñ*¨9Ô5ÀDˆô �gœt×$Ò$Øˆ|ÐÜ”—‘˜uÐXÑ'W±wÓ'WÐXÓYÓZÐZøô	 ”z¤>Ð2ô ØŠðús   ¹6B0 Â0CÃ
Cc           
     ó  € \        4       / r!V P                  R\        R,           34      P                  4       pV EFG  w  p\        P
                  ! V4      pVP                  R4      VP                  R4      rv\        V\        4      '       d;   \        ;QJ d    R V 4       F  '       d   K   RM	  RM! R V 4       4      '       g   K�  RP                  R	\        V4      ,          4      p\        V P                  R
V R2V4      P                  4       4      p	\        V4       U
Uu. uF3  w  r«V
^ 8X  g&   V	P                  Wz^,
          ,          4      R8X  g   K1  VNK5  	  pp
pVP                  VRR 4       Wg3W,R,          &   EKJ  	  W3# u upp
i )a  ``(superseded, heads)`` for listing a local conversation as one row, as
``acp_adapter.catalog`` does: a canonical reset keeps the creation id as the owner and moves the
transcript to a child, so every segment is one conversation. ``superseded`` holds the listable
roots of earlier reset segments (filtered in SQL, before paging); ``heads`` maps the latest
reset segment to ``(owner, lineage)`` for the row that represents the conversation. A delete
of that row removes the whole lineage (``hermes_state_mutation_guards.delete_targets``).zqSELECT value FROM state_meta WHERE key GLOB ? AND json_valid(value) AND json_array_length(value, '$.lineage') > 1rn   r   rx   c              3   óB   "  € T F  p\        V\        4      x € K  	  R # 5ir   r„   r…   s   & r   r   Ú&local_lineage_index.<locals>.<genexpr>Ý   s   é € Ð0YÑQXÈ#´¸CÄ×1EÐ1EÓQXùs   ‚FTÚ,Ú?z0SELECT id,end_reason FROM sessions WHERE id IN (Ú)Úsession_resetNéÿÿÿÿ)ro   r+   rM   Úfetchallr-   r.   rK   rf   rh   r/   ÚjoinÚlenrg   Ú	enumerateÚupdate)r<   Ú
supersededÚheadsÚrowsrk   r   r|   rx   ÚmarksÚendedÚirG   Ústartss   &            r   Úlocal_lineage_indexr›   Ð   sS  € ô ›˜r�Ø�<‰<ð HÜJWÐZ]ÕJ]ÐI_óaßaiÑaiÓakð 	ä‰ˆÜ—*’*˜S“/ˆØ Ÿ™ \Ó2°G·K±KÀ	Ó4JˆwÜ˜%¤×%Ò%¯S«SÑ0YÑQXÓ0Y¯S¯SªSÑ0YÑQXÓ0Y×-YÒ-YÙØ—‘˜œs 7›|Õ+Ó,ˆÜ�T—\‘\Ð$TÐUZÐT[Ð[\Ð"]Ð_fÓg×pÑpÓrÓsˆÜ$-¨gÔ$6ÔqÑ$6™&˜!¸!¸q¼&ÀEÇIÁIÈgÐZ[ÕV[ÍnÓD]ÐapÑDp—#�#Ñ$6ˆÑqØ×Ñ˜&  "˜+Ô&Ø"Ð,ˆ�R�jÔñ ð ÐÐùó rs   Ä%.F	ÅF	c                ó  € V P                  4       ;_uu_ 4       p\        V4      w  rERRR4       X'       d@   VP                  R4       VP                  \        P                  ! \        V4      4      4       X#   + '       g   i     LY; i)z£Drop earlier reset segments from a listing or count query (one conversation, one row),
in SQL before paging; returns ``heads`` for :func:`annotate_local_lineages`.Nz,s.id NOT IN (SELECT value FROM json_each(?)))Ú	_read_ctxr›   Úappendr-   ÚdumpsÚsorted)rB   Úwhere_clausesÚparamsr<   r”   r•   s   &&&   r   Úexclude_superseded_segmentsr£   ç   s\   € ð 
�‰�Œ˜4Ü/°Ó5Ñˆ
÷ 
çØ×ÑÐKÔLØ�‰”d—j’j¤¨
Ó!3Ó4Ô5Ø€L÷ 
�ús   ™A8Á8B	c           	     ó  € V  F  pTP                  VP                  R4      ;'       g
    VR,          4      pVf   K:  \        \        P                  . V^,          OVP                  R4      ;'       g    RO4      4      VR&   K�  	  V # )a  Name every segment on the conversation's representative row (``_lineage_ids``, which the
Desktop matches deletes, tombstones and stored ids against). ``_lineage_root_id`` stays the
compression root: pins and archive flags live on the listed segment's own chain.Ú_lineage_root_idÚidÚ_lineage_idsr   )rK   rz   rg   r   )Úsessionsr•   r{   Úfounds   &&  r   Úannotate_local_lineagesrª   ò   sx   € ó ˆØ—	‘	˜#Ÿ'™'Ð"4Ó5×BÐB¸¸T½ÓCˆØÔÜ"&¤t§}¡}Ð5b°u¸QµxÐ5bÀ3Ç7Á7È>ÓCZ×C`ÐC`Ð^`Ð5bÓ'cÓ"dˆC�Óñ ð €OrY   c                 ó¬  € V P                  4       ;_uu_ 4       pVP                  R \        V,           34      P                  4       pRRR4       Xf   \	        R4      h \
        P                  ! V^ ,          4      p\        V\        4      '       g   \        R4      hV#   + '       g   i     L`; i  \        \        3 d   p\	        R4      ThRp?ii ; i)r   Nr   zinvalid receipt)r�   r+   rM   r,   r   r-   r.   rf   rg   r1   r2   )rB   r   r<   r{   ri   r?   s   &&    r   Úlocal_receiptr¬   ý   s¬   € Ø	�‰�Œ˜4Ø�l‰lÐEÌÐXbÕHbÐGdÓe×nÑnÓpˆ÷ 
à
‚{ÜÐ 5Ó6Ð6ð@Ü—
’
˜3˜q�6Ó"ˆÜ˜%¤×&Ò&ÜÐ.Ó/Ð/Øˆ÷ 
�ûô ”zÐ"ô @ÜÐ 5Ó6¸CÐ?ûð@ús#   ™-BÁ?B1 ÂB.	Â1CÃCÃCc               óB   a aaaa€ V VVVV3R lpS P                  V4      # )a  Stamp ``ended_at`` on *target_id* only while the logical *session_id*'s FIFO is idle.

The idle check and the stamp share one owner write txn, so an admission committed first keeps
the row open; one committed after is reopened by the drain (``reopen_local_session``).c                 ó  <€ \        V S4       V P                  R S34      P                  4       '       d   ^ # V P                  RSS34      P                  4       '       d   ^ # SP                  V R\        P                  ! 4       SS3SS4      # )zgSELECT 1 FROM session_admissions WHERE target_session_id=? AND status IN ('queued','started','unknown')zjSELECT 1 FROM worker_executions WHERE session_id IN (?,?) AND status IN ('registered','running','unknown')zLUPDATE sessions SET ended_at=?, end_reason=? WHERE id=? AND ended_at IS NULL)r   r+   r,   Ú_end_and_bumpÚtime)r<   rB   rD   Úreasonr   Ú	target_ids   &€€€€€r   rH   Ú%end_idle_local_session.<locals>.write  sŠ   ø€ Üˆt�UÔØ�<‰<ð  BØ#˜ó'ß'/¡x£zö2áØ�<‰<ð  EØ# YÐ/ó1ß19±³ö<áØ×Ñ Ð&tÜ!%§¢£¨f°iÐ @À)ÈVóUð 	UrY   )rN   )rB   rD   r   r²   r±   rH   s   fdddd r   Úend_idle_local_sessionr´     s"   ü€ ÷
	Uñ 	Uð ×Ñ˜UÓ#Ð#rY   r   )Ú__doc__r-   r°   Úhermes_state_runtimer   r   r   rM   rq   rp   rQ   r   r^   r0   r9   rl   rv   r}   r�   r€   r›   r£   rª   r¬   r´   r   rY   r   Ú<module>r·      sz   ðÙ QÛ Û ç AÑ Aà*€Ø.Ð Ø4Ð òHôVò"+òyò	Lò	HòUò&XòXò[òò.òò@ô$rY   