+
    jHàji1  ã                  ó   a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
HtH
t
HtHtHt ^ RIHt ^RIHt ^RIHt ]P,                  ! ]4      t^2tRt]! ]P8                  4      ]! ]P:                  4      ,          tRt^t ]PB                  ! R	4      t"]	PF                  ! 4       t$/ t%R
]&R&   R R lt'R R lt(R R lt)R^RR/R R llt*R R lt+R R lt,R R lt-R R lt.R R lt/R  R! lt0R" R# lt1R$ R% lt2R& R' lt3R?R( R) llt4R* R+ lt5R, R- lt6R. R/ lt7R0 R1 lt8R2 R3 lt9R4 R5 lt:R6 R7 lt;R8 R9 lt<R: R; lt=R<R/R= R> llt>R# )@aÚ  Shared-metrics facts the Desktop app reports about itself: area use, friction, first-run steps,
dislike signals, and one daily report (Bot Mode / Sessions split, button presses per action).

The renderer dedupes on its side (per-profile state persisted only while collection is on); the
backend latches again so a second window, a reconnect replay, a backend restart or a cleared
localStorage cannot inflate a row. Feature use (once per profile, UTC day, area) and the daily report
(once per profile and usage day, counted in the usage day's period) latch durably in the profile's
shared-metrics store, in the same transaction as the row; onboarding latches once per (profile, step,
event) ever in a file; friction and dislike are capped per (profile, UTC day) in this process. Every
value collapses onto the closed sets in ``shared_metrics_contract``; raw client words are never
recorded. Every latch is claimed only after the ``enabled()`` gate, so a disabled profile writes nothing.
)ÚannotationsN)ÚdateÚdatetimeÚ	timedeltaÚtimezoneÚUTC)ÚAny)Úshared_metrics_contract)Ú_emitÚdesktop_onboardingÚdesktop_daily_reportedz\d{4}-\d{2}-\d{2}zdict[tuple[str, str, str], int]Ú_dailyc               ó   € V ^8„  d   QhRR/# ©é   ÚreturnÚstr© )Úformats   "ÚT/home/ubuntu/.hermes/hermes-agent/hermes_cli/observability/shared_metrics_desktop.pyÚ__annotate__r   .   s   € ÷ 0ñ 0�#ñ 0ó    c                 ón   € \         P                  ! \        4      P                  4       P	                  4       # )N)r   Únowr   r   Ú	isoformatr   r   r   Ú_utc_dayr   .   s#   € Ü�<Š<œÓ×!Ñ!Ó#×-Ñ-Ó/Ð/r   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   2   s   € ÷ "ñ "ˆsñ "r   c                 ó.   € ^ RI Hp  \        V ! 4       4      # )é    ©Úget_hermes_home)Úhermes_constantsr    r   r   s    r   Ú_homer"   2   s   € Ý0ä‰Ó Ó!Ð!r   c               ó    € V ^8„  d   QhRRRR/# )r   Úvaluer   r   r   r   )r   s   "r   r   r   8   s   € ÷ Cñ C�ð C˜ñ Cr   c                ón   € \        V \        4      '       d   V P                  4       P                  4       # R # ©Ú )Ú
isinstancer   ÚstripÚlower©r$   s   &r   Ú_wordr,   8   s(   € Ü$.¨u´c×$:Ò$:ˆ5�;‰;‹=×ÑÓ ÐBÀÐBr   ÚcapÚdayc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úkeyr   r-   Úintr.   z
str | Noner   Úboolr   )r   s   "r   r   r   <   s(   € ÷ 
ñ 
�cð 
 3ð 
°ð 
Àtñ 
r   c               óÐ  € \        4       p\        4       T;'       g    TV 3p\        ;_uu_ 4        \         Uu. uF+  qU^,          V8  g   K  V^,          V^,          8w  g   K)  VNK-  	  up F
  p\        V K  	  \        P	                  V^ 4      V8¼  d    RRR4       R# \        P	                  V^ 4      ^,           \        V&   RRR4       R# u upi   + '       g   i     R# ; i)zSTrue while ``key`` has been claimed fewer than ``cap`` times today in this profile.NFT)r   r"   Ú_LATCH_LOCKr   Úget)r0   r-   r.   ÚtodayÚslotÚkÚstales   &$$    r   Ú_claim_dailyr:   <   s²   € ä‹J€EÜ‹G�S—\�\˜E 3Ð'€Dß	ŽÝ!'ÓL¡˜A¨Q­4°%©<”a¸A¸a½DÀDÈÅG¹O—a�a¡ÔLˆEÜ�u’ñ Mä�:‰:�d˜AÓ #Ô%Ø÷	 
‰ô
 —z‘z $¨Ó*¨QÕ.Œˆt‰÷ 
ñ ùò M÷ 
Žñ ús.   °	C¹CÁCÁ$CÁ*-CÂ!$CÃCÃC%	c               ó    € V ^8„  d   QhRRRR/# )r   Úarear   r   r   r   )r   s   "r   r   r   I   s   € ÷ Iñ I�sð I˜sñ Ir   c                ó|   € \        V 4      pV\        P                  9   d   V# VP                  R 4      '       d   R# R# )Ú	settings_Úsettings_otherÚother)r,   ÚcontractÚDESKTOP_FEATURE_AREASÚ
startswith)r<   Úwords   & r   Úfeature_arearE   I   s8   € Ü�‹;€DØŒx×-Ñ-Ô-ØˆØ#Ÿ™¨{×;Ò;ÐÐHÀÐHr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úkindr   Údetailr   ztuple[str, str] | Noner   )r   s   "r   r   r   P   s'   € ÷ Iñ I˜ð I Sð IÐ-Cñ Ir   c                ó’   € \        V 4      p\        P                  P                  V4      pVf   R# \        V4      pY$V9   d   V3# R3# )z\``(kind, detail)`` with detail checked against ITS kind's set; unknown kinds record nothing.Nr@   )r,   rA   ÚDESKTOP_FRICTION_DETAILSr5   )rG   rH   Ú	kind_wordÚdetailsÚdetail_words   &&   r   Úfriction_pairrN   P   sJ   € ä�d“€IÜ×/Ñ/×3Ñ3°IÓ>€GØ‚ÙÜ˜“-€KØ°GÔ%;�kÐHÐHÀÐHÐHr   c               ó   € V ^8„  d   QhRR/# )r   r   ztuple[Any, dict[str, str]]r   )r   s   "r   r   r   Z   s   € ÷ ñ Ð7ñ r   c                 óÜ   € ^ RI Hp  ^RIHp ^RIHp V! 4       \        P                  ! V ! 4       P                  \        P                  ! 4       \        P                  ! 4       V! 4       R7      3# )z«The active profile's store and client resource (the subscriber's), for rows that latch
durably or belong to a past period and so cannot ride the relay's current-day marks.)Úget_version_info)ÚSharedMetricsStore)Údetect_client_install_method)Úos_nameÚarchitectureÚinstall_method)Úhermes_cli.version_inforQ   Úshared_metricsrR   Úshared_metrics_installrS   rA   Úclient_resourceÚbase_versionÚplatformÚsystemÚmachine)rQ   rR   rS   s      r   Ú_store_and_resourcer_   Z   sQ   € õ 9å2ÝDáÓ¤×!9Ò!9ÙÓ×'Ñ'´·²Ó1BÔQY×QaÒQaÓQcÙ3Ó5ô"ð ð r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rG   r   rH   r   údict[str, str] | Noner   )r   s   "r   r   r   h   s"   € ÷ 0ñ 0˜cð 0¨3ð 0Ð3Hñ 0r   c                ó¢   € \        W4      pVe,   \        RV^ ,           RV^,           2\        R7      '       g   R # RV^,          RV^ ,          /# )Nz	friction:Ú:©r-   rH   rG   )rN   r:   ÚFRICTION_DAILY_CAP)rG   rH   Úpairs   $$ r   Ú_friction_fieldsrg   h   sM   € Ü˜Ó&€DØ‚|œ<¨)°D¸µG°9¸A¸dÀ1½g¸YÐ(GÔM_×`Ó`ÙØ�d˜1•g˜v t¨A¥wÐ/Ð/r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Ústepr   Úeventr   r2   r   )r   s   "r   r   r   o   s!   € ÷ 
ñ 
˜Cð 
¨ð 
°ñ 
r   c                óz  € ^ RI Hp V! 4       R,          R,          \        ,          pVP                  RRR7        \        P
                  ! \        P                  ! W0 RV 2,          \        P                  \        P                  ,          \        P                  ,          4      4       R#   \         d     R# i ; i)u]   Once per (step, event) per profile, across processes: an O_EXCL latch file (â‰¤ ~51 of them).r   Ú	telemetryrX   T)ÚparentsÚexist_okÚ.F)r!   r    ÚONBOARDING_LATCH_DIRNAMEÚmkdirÚosÚcloseÚopenÚO_CREATÚO_EXCLÚO_WRONLYÚFileExistsError)ri   rj   r    Ú	directorys   &&  r   Ú_claim_onboardingrz   o   sŠ   € å0áÓ! KÕ/Ð2BÕBÔE]Õ]€IØ‡O�O˜D¨4€OÔ0ðÜ
�Š”—’˜ v¨Q¨u¨gÐ%6Õ6¼¿
¹
ÄRÇYÁYÕ8NÔQS×Q\ÑQ\Õ8\Ó]Ô^ñ øô ô Úðús   »A.B+ Â+B:Â9B:c               ó   € V ^8„  d   QhRR/# )r   r   ÚNoner   )r   s   "r   r   r   |   s   € ÷ uñ u $ñ ur   c                 ó~   € ^ RI Hp  \        P                  ! V ! 4       R,          R,          \        ,          RR7       R# )z`Collection turned off: drop the per-profile onboarding latches like the renderer drops its copy.r   rl   rX   T)Úignore_errorsN)r!   r    ÚshutilÚrmtreerp   r   s    r   Úpurge_onboarding_latchesr�   |   s(   € å0ä
‡M‚M‘/Ó# kÕ1Ð4DÕDÔG_Õ_Ðos×tr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   ri   r   rj   r   ra   r   )r   s   "r   r   r   ƒ   s'   € ÷ jñ j ð j¨Cð jÐ4Iñ jr   c                ó¶   € \        V 4      \        V4      r2V\        P                  9  g   V\        P                  9  d   R # \	        W#4      '       d   RVRV/# R # )Nrj   ri   )r,   rA   ÚDESKTOP_ONBOARDING_STEPSÚDESKTOP_ONBOARDING_EVENTSrz   )ri   rj   Ú	step_wordÚ
event_words   $$  r   Ú_onboarding_fieldsrˆ   ƒ   sN   € Ü! $›K¬¨u«ˆzØœ×9Ñ9Ô9¸ZÌx×OqÑOqÔ=qÙÜ7HÈ×7_Ò7_ˆG�Z ¨Ð3ÐiÐeiÐir   c               ó    € V ^8„  d   QhRRRR/# )r   r$   r   r   r1   r   )r   s   "r   r   r   Š   s   € ÷ oñ o�#ð o˜#ñ or   c                óŽ   € \        V \        \        34      '       d)   \        V \        4      '       g   V ^ 8¼  d   \        V 4      # ^ # )r   )r(   r1   Úfloatr2   r+   s   &r   Ú_countrŒ   Š   s8   € Ü# E¬C´¨<×8Ò8ÄÈEÔSW×AXÒAXÐ]bÐfgÔ]gŒ3ˆu‹:ÐnÐmnÐnr   c               ó    € V ^8„  d   QhRRRR/# )r   Úactionr   r   r   r   )r   s   "r   r   r   Ž   s   € ÷ Dñ D�cð D˜cñ Dr   c                ó„   € \        V \        4      '       d   V P                  4       MRpV\        P                  9   d   V# R# )zUAction ids are case-sensitive registry ids (``view.toggleSidebar``): only strip them.r'   r@   )r(   r   r)   rA   ÚDESKTOP_ACTION_IDS)rŽ   rD   s   & r   Ú	action_idr‘   Ž   s3   € ä'¨´×4Ò4ˆ6�<‰<Œ>¸"€DØœ8×6Ñ6Ô6ˆ4ÐC¸GÐCr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   ÚconfigÚdictÚprefixr   r   zdict[str, Any]r   )r   s   "r   r   r   ”   s!   € ÷ ñ ˜Dð ¨#ð °~ñ r   c                óì   € / pV P                  4        F]  w  r4V'       d   V R V 2M
\        V4      p\        V\        4      '       d%   V'       d   VP	                  \        WE4      4       KY  WBV&   K_  	  V# )ro   )Úitemsr   r(   r”   ÚupdateÚ_setting_leaves)r“   r•   Úleavesr0   r$   Úpaths   &&    r   r™   r™   ”   s_   € Ø€FØ—l‘l–n‰
ˆß$*�&�˜˜3˜%Ñ ´°C³ˆÜ�eœT×"Ò"§uØ�M‰Mœ/¨%Ó6Ö7à �4‹Lñ %ð €Mr   c               ó    € V ^8„  d   QhRRRR/# )r   r0   r   r   ztuple[str, str]r   )r   s   "r   r   r   Ÿ   s   € ÷ Rñ R˜Cð R Oñ Rr   c                ó*  € ^ RI HpHp \        V4      pW9  g   \	        V 4      \
        P                  8”  d   R# V! 4       pV P                  R4       F,  p\        V\        4      '       d   VP                  V4      MRpK.  	  YW0,          8X  d   R3# R3# )a  ``(setting, direction)`` for a config key the Desktop settings page just saved: the key only if
it is a DEFAULT_CONFIG leaf (the settings schema), the direction from comparing the saved value to
the default here in the backend, so the value never leaves this process.)ÚDEFAULT_CONFIGÚload_configro   NÚ
to_defaultÚaway_from_default)r@   Únone)Úhermes_cli.configrž   rŸ   r™   ÚlenrA   ÚDESKTOP_SETTING_KEY_MAX_LENGTHÚsplitr(   r”   r5   )r0   rž   rŸ   ÚdefaultsÚcurrentÚparts   &     r   Ú_setting_directionrª   Ÿ   s~   € ÷ >ä˜~Ó.€HØ
Ôœc #›h¬×)PÑ)PÔPØÐÙ“=€GØ—	‘	˜#–ˆÜ'1°'¼4×'@Ò'@�'—+‘+˜dÔ#ÀdŠñ à¨8­=Ô 8�ÐQÐQÐ>QÐQÐQr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Úsignalr   ÚtargetÚsettingr   ra   r   )r   s   "r   r   r   ®   s/   € ÷ kñ k˜sð k¨Cð k¸#ð kÐBWñ kr   c                óÊ  € \        V 4      p\        P                  P                  V4      pVf   R # VR8X  d9   \	        V\
        4      '       d   VP                  4       MRp\        V4      w  rgRpMO\	        V\
        4      '       d   VP                  4       MRp	VR8X  d	   W”9   d   T	M
\        V	4      pW„9   d   TMRpRRrv\        RV 2\        R7      '       g   R # R	VRVR
VRV/# )NÚsetting_off_defaultr'   r®   Ú
rage_clickr@   r¢   zdislike:rd   Ú	directionr¬   r­   )
r,   rA   ÚDESKTOP_DISLIKE_TARGETSr5   r(   r   r)   rª   r:   re   )
r¬   r­   r®   Úsignal_wordÚtargetsr0   Úsetting_wordr²   Útarget_wordÚraws
   $$$       r   Ú_dislike_fieldsr¹   ®   sÓ   € Ü˜“-€KÜ×.Ñ.×2Ñ2°;Ó?€GØ‚ÙØÐ+Ô+Ü!+¨G´S×!9Ò!9ˆg�m‰mŒo¸rˆÜ"4°SÓ"9ÑˆØ‰ä *¨6´3× 7Ò 7ˆf�l‰lŒn¸RˆØ(¨LÔ8¸S¼^‘cÔQVÐWZÓQ[ˆØ%0Ô%;‘kÀˆØ"(¨&�iÜ˜( ; -Ð0Ô6H×IÓIÙØ˜ I¨|¸XÀ{ÐT\Ð^iÐjÐjr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úmodesr   Ú	bot_countr   ú list[tuple[str, dict[str, str]]]r   )r   s   "r   r   r   Á   s"   € ÷ ñ �cð  cð Ð.Nñ r   c           
     ó~  € / p\        V \        4      '       d   T M.  EF  p\        V\        4      '       d   \        VP	                  R 4      4      MRpV'       d5   \        VP	                  R4      4      \        VP	                  R4      4      3MRw  rVV\        P                  9  g   WB9   g   V'       g   V'       g   K£  \        P                  R\        P                  ! V4      R\        P                  ! \        V4      4      R\        P                  ! V4      R V/3W$&   EK  	  \        VP                  4       4      # )Úmoder'   Ú	active_msÚmessages_sentÚactive_minutes_bucketÚbot_count_bucketÚmessages_sent_bucket)r   r   )r(   Úlistr”   r,   r5   rŒ   rA   ÚDESKTOP_MODESÚDESKTOP_MODE_USE_MARKÚdesktop_active_minutes_bucketÚsize_bucketÚvalues)r»   r¼   ÚrowsÚentryr¿   rÀ   Úmessagess   &&     r   Ú
_mode_rowsrÎ   Á   sð   € Ø24€DÜ$ U¬D×1Ò1‘°rÓ9ˆÜ+5°e¼T×+BÒ+BŒu�U—Y‘Y˜vÓ&Ô'Èˆßfjœv e§i¡i°Ó&<Ó=¼vÀeÇiÁiÐP_ÓF`Ó?aÑbÐpvÑˆ	à”x×-Ñ-Ô-°´Çi×S[ÙÜ×4Ñ4Ø#¤X×%KÒ%KÈIÓ%VØ¤× 4Ò 4´V¸IÓ5FÓ GØ"¤H×$8Ò$8¸Ó$BØ�Dð	7
ð ˆŒ
ñ :ô �—‘“ÓÐr   c               ó    € V ^8„  d   QhRRRR/# )r   Úactionsr   r   r½   r   )r   s   "r   r   r   Ò   s   € ÷ 
ñ 
˜#ð 
Ð"Bñ 
r   c                ó†  € / p\        V \        4      '       d   T M. R \          F¯  p\        V\        4      '       d.   \	        VP                  R4      4      \        P                  9  d   KH  \        VP                  R4      4      \	        VP                  R4      4      3pVP                  V^ 4      \        VP                  R4      4      ,           W&   K±  	  \        VP                  4       4       UUUu. uF=  w  w  rEqf'       g   K  \        P                  RVR\        P                  ! V4      RV/3NK?  	  uppp# u upppi )NÚviarŽ   ÚcountÚcount_bucket)r(   rÅ   ÚDAILY_ACTION_ROWS_MAXr”   r,   r5   rA   ÚDESKTOP_ACTION_VIASr‘   rŒ   Úsortedr—   ÚDESKTOP_ACTION_USE_MARKrÉ   )rÐ   ÚtotalsrÌ   r0   rŽ   rÒ   rÓ   s   &      r   Ú_action_rowsrÚ   Ò   s  € Ø)+€FÜ'¨´×6Ò6‘'¸BÐ@VÔAVÓWˆÜ˜%¤×&Ò&¬%°·	±	¸%Ó0@Ó*AÌ×IeÑIeÔ*eÙÜ˜Ÿ™ 8Ó,Ó-¬u°U·Y±Y¸uÓ5EÓ/FÐGˆØ—j‘j  aÓ(¬6°%·)±)¸GÓ2DÓ+EÕEˆ‹ñ	 Xô %+¨6¯<©<«>Ô$:õá$:Ñ ‰MˆV˜5»eô 	xŒ×	)Ñ	)¨H°f¸nÌh×NbÒNbÐchÓNiÐkpÐruÐ+vÓwÙ$:óð ùô s   Ã4D<Ä0D<c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Ú	usage_dayr   ÚoldestÚmarksr½   Úresourcezdict[str, str]r   )r   s   "r   r   r   ß   s*   € ÷ ñ ˜Sð ¨#ð Ð6Vð Ðbpñ r   c                ó&   a aaa€ R VVVV 3R llpV# )zY``update_rollup_state`` step: the usage day's rows, unless that day was already reported.c               ó    € V ^8„  d   QhRRRR/# )r   Ústatezdict[str, Any] | Noner   z8tuple[dict[str, Any], list[tuple[str, dict, dict, str]]]r   )r   s   "r   r   Ú#_daily_rollup.<locals>.__annotate__á   s    € ÷ qñ qÐ+ð qÐ0hñ qr   c           	     ó   <€ T ;'       g    / P                  R . 4       Uu. uF&  p\        V\        4      '       g   K  VS8¼  g   K$  VNK(  	  ppSV9   d   R V/. 3# R \        . VOSN4      /S UUu. uF
  w  r4W4SS3NK  	  upp3# u upi u uppi ©Údays)r5   r(   r   r×   )	râ   Údræ   ÚmarkÚdatarÞ   rÝ   rß   rÜ   s	   &    €€€€r   r˜   Ú_daily_rollup.<locals>.updateá   s¢   ø€ Ø!ŸK˜K R×,Ñ,¨V°RÔ8Ó_Ñ8�a¼JÀqÌ#×<N”ÐSTÐX^ÑS^—�Ñ8ˆÐ_Ø˜ÔØ˜D�> 2Ð%Ð%ØœÐ1 Ð1 yÐ1Ó2Ð3ÑjoÔ5pÑjoÑ\fÐ\`°tÀ8ÈYÓ6WÑjoÒ5pÐpÐpùò `ùó 6qs    B½BÁBÁ0B
r   )rÜ   rÝ   rÞ   rß   r˜   s   ffff r   Ú_daily_rolluprë   ß   s   û€ ÷qó qð
 €Mr   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )r   r.   r   r»   rÐ   r¼   r   r2   r   )r   s   "r   r   r   é   s0   € ÷ ñ  ð ¨Sð ¸3ð È3ð ÐSWñ r   c           	     óH  €  ^RI Hp V! 4       '       g   R# \        4       p\        P                  ! V4      \        \        R7      ,
          P                  4       p\        V \        4      '       d/   \        P                  V 4      '       d   Y`u;8:  d   V8:  d   M MT MRpV'       d   \        W4      \        V4      ,           M. pV'       d-   \        4       w  ršV	P                  \         \#        WvWŠ4      4       R#   \$         d    \&        P)                  RRR7        R# i ; i)a€  Record one finished Desktop day, in that day's period: a mode_use row per mode used (with the
bot count) and an action_use row per (action, via). True once the day is settled (saved, already
reported, empty or out of range) so the client drops its copy; False keeps it for the next attach,
including when this profile's collection is off (the client's own gate decides what it keeps).©ÚenabledFrå   NTz!Desktop daily report not recorded©Úexc_info)Úrelay_shared_metricsrï   r   r   Úfromisoformatr   ÚDAILY_REPORT_WINDOW_DAYSr   r(   r   Ú_DAYÚ	fullmatchrÎ   rÚ   r_   Úupdate_rollup_stateÚDAILY_REPORT_STATE_KEYrë   Ú	ExceptionÚloggerÚdebug)r.   r»   rÐ   r¼   rï   r6   rÝ   rÜ   rÞ   Ústorerß   s   $$$$       r   Úrecord_desktop_dailyrý   é   sÑ   € ð
Ý1á�yŠyÙÜ“
ˆÜ×$Ò$ UÓ+¬iÔ=UÔ.VÕV×aÑaÓcˆÜ% c¬3×/Ò/´D·N±NÀ3×4GÒ4GÈFÖLbÐ]b×Lb‘CÐhlˆ	ßHQ”
˜5Ó,¬|¸GÓ/DÖDÐWYˆßÜ1Ó3‰OˆEØ×%Ñ%Ô&<¼mÈIÐ_dÓ>oÔpÙøÜô Ü�‰Ð8À4ˆÔHÚðús)   ‚C; —A3C; ÂC; Â($C; Ã,C; Ã;"D!Ä D!c               ó    € V ^8„  d   QhRRRR/# )r   r<   r   r   r|   r   )r   s   "r   r   r      s   € ÷ 	Hñ 	H¨ð 	H°ñ 	Hr   c                óô   €  ^RI Hp V! 4       '       d;   \        4       w  r#VP                  \        P
                  R\        V 4      /V4       R# R#   \         d    \        P                  RRR7        R# i ; i)zTOnce per (profile, UTC day, area), latched in the store with the row (never raises).rî   r<   z Desktop feature use not recordedTrð   N)
rò   rï   r_   Úrecord_counter_once_per_dayrA   ÚDESKTOP_FEATURE_USE_METRICrE   rù   rú   rû   )r<   rï   rü   rß   s   $   r   Úrecord_desktop_feature_user     sk   € ðHÝ1á�9Š9Ü1Ó3‰OˆEØ×-Ñ-¬h×.QÑ.QÐTZÔ\hÐimÓ\nÐSoÐqyÖzñ øô ô HÜ�‰Ð7À$ˆ×GðHús   ‚A •8A Á"A7Á6A7c               ó$   € V ^8„  d   QhRRRRRR/# )r   rG   r   rH   r   r|   r   )r   s   "r   r   r     s&   € ÷ Vñ V Sð V°#ð V¸$ñ Vr   c                óF   € \        \        P                  \        WR 7       R# )©rG   rH   N)r
   rA   ÚDESKTOP_FRICTION_MARKrg   r  s   $$r   Úrecord_desktop_frictionr    s   € Ü	Œ(×
(Ñ
(Ô*:À×Ur   c               ó$   € V ^8„  d   QhRRRRRR/# )r   ri   r   rj   r   r|   r   )r   s   "r   r   r     s&   € ÷ Xñ X sð X°3ð X¸4ñ Xr   c                óF   € \        \        P                  \        WR 7       R# )©ri   rj   N)r
   rA   ÚDESKTOP_ONBOARDING_MARKrˆ   r
  s   $$r   Úrecord_desktop_onboardingr    s   € Ü	Œ(×
*Ñ
*Ô,>ÀT×Wr   r®   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r¬   r   r­   r®   r   r|   r   )r   s   "r   r   r     s/   € ÷ iñ i cð i°3ð iÀð iÐPTñ ir   c                óH   € \        \        P                  \        WVR 7       R# )©r¬   r­   r®   N)r
   rA   ÚDESKTOP_DISLIKE_MARKr¹   r  s   $$$r   Úrecord_desktop_disliker    s   € Ü	Œ(×
'Ñ
'¬ÀÐ`g×hr   r&   )?Ú__conditional_annotations__Ú__doc__Ú
__future__r   Úloggingrr   r\   Úrer   Ú	threadingr   r   r   r   r   Útypingr   r'   r	   rA   Úshared_metrics_eventsr
   Ú	getLoggerÚ__name__rú   re   rp   r¤   r�   rÖ   rÕ   rø   rô   Úcompilerõ   ÚLockr4   r   Ú__annotations__r   r"   r,   r:   rE   rN   r_   rg   rz   r�   rˆ   rŒ   r‘   r™   rª   r¹   rÎ   rÚ   rë   rý   r  r  r  r  )r  s   @r   Ú<module>r     sE  øðôõ #ã Û 	Û Û 	Û Û ß =Õ =Ý å 1Ý (à	×	Ò	˜8Ó	$€ð Ð Ø/Ð á˜H×7Ñ7Ó8¹3¸x×?[Ñ?[Ó;\Õ\Ð Ø1Ð ð Ð Ø	‡z‚zÐ&Ó'€Ø�nŠnÓ€à*,€Ð'Ó ,õ0õ"õCð
¨ð 
¸d÷ 
õIõIõõ0õ
õuõjõoõD÷õRõkõ&õ"
õõõ.	HõVõXðiÀt÷ iñ ir   