+
    „WÝjû-  ã            
      óT  € R t ^ RIHt ^ RIt^ RIt^ RIHt ^ RIHtH	t	 Rt
^tR R 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tR(R R lltR(R R lltR R ltR)R R llt]P.                  ! 4       tRRRRRRRR/R  R! lltRR/R" R# lltR$RRRR%RRRRR/R& R' lltR# )*u  The plugin update-check cadence: read-only, receipt-surfaced.

Runs at gateway start + the periodic tick when
``plugins.auto_update_check_hours`` (default 24, 0 disables) says it's
due, writes a plugin-check receipt (pm.receipt, kind 'plugin-check'),
and logs ONE actionable line when updates exist. Applying updates
stays explicit â€” ``plugins.auto_apply: true`` (default false) opts into
unattended apply for git-row plugins ONLY, scan-gated like cmd_update.

Pure, injectable clock/check/update seams for hermetic tests.
)ÚannotationsN)ÚPath)ÚCallableÚOptionalzplugin-update-checksc               ó   € V ^8„  d   QhRR/# ©é   Úreturnr   © )Úformats   "ÚNC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\plugins_cadence.pyÚ__annotate__r      s   € ÷ 9ñ 9�dñ 9ó    c                 ó@   € ^ RI Hp  V ! 4       \        ,          R,          # )u¢   The last-run marker, resolved per call (tests monkeypatch
get_hermes_home). Derivation only â€” NO mkdir: a due-check or any
read path must not create user state.©Úget_hermes_homeúlast-run)Úhermes_constantsr   Ú_MARKERS_DIRr   s    r   Ú_marker_pathr      s   € õ 1áÓœ|Õ+¨jÕ8Ð8r   c               ó   € V ^8„  d   QhRR/# r   r
   )r   s   "r   r   r   !   s   € ÷ 2ñ 2�tñ 2r   c                 ó8   € \        4       P                  R,          # )zJThe last check's per-plugin results, next to the marker (derivation only).úresults.json)r   Úparentr
   r   r   Ú_results_pathr   !   s   € ä‹>× Ñ  >Õ1Ð1r   c               ó    € V ^8„  d   QhRRRR/# )r   Úplugins_dirr   r	   Údictr
   )r   s   "r   r   r   &   s   € ÷ *ñ * 4ð *¨Dñ *r   c                ó   € ^ RI Hp V! V 4      # )z¶The install records an update check is about to compare against. Take it BEFORE the check runs:
a record read afterwards may already include an update that finished during the check.)Úread_sidecar_rows)Úhermes_cli.plugins_provenancer   )r   r   s   & r   Úsnapshot_installsr!   &   s   € õ @á˜[Ó)Ð)r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   ÚresultsÚlistÚchecked_installsr   r	   ÚNoner
   )r   s   "r   r   r   .   s!   € ÷ ñ  $ð ¸$ð À4ñ r   c                ó¢  € ^ RI p^ RIHp  . pV  Fn  p\        VR4      '       d   VP	                  4       M
\        V4      pVP                  / VCR\        VP                  VP                  R4      4      4      /C4       Kp  	  V! \        4       R,          VP                  V^R7      R,           4       R#   \        \        \        3 d     R# i ; i)	aU  Persist a completed check so surfaces that list plugins (the Desktop Plugins tab) can show an
update without a network call per listing. Each row carries the install record it was checked
against (*checked_installs*, from :func:`snapshot_installs` before the check), so a later reader
can tell whether the result still applies. Never raises.N)Úatomic_write_textÚto_jsonÚchecked_installÚnamer   )ÚindentÚ
)ÚjsonÚutilsr(   Úhasattrr)   r   ÚappendÚ_install_fingerprintÚgetÚ_markers_dirÚdumpsÚOSErrorÚ	TypeErrorÚ
ValueError)r#   r%   r.   r(   ÚrowsÚrÚrows   &&     r   Úrecord_check_resultsr<   .   s´   € ó
 å'ðØˆÛˆAÜ!(¨¨I×!6Ò!6�!—)‘)”+¼DÀ»GˆCØ�K‰KÐo˜3ÐoÐ 1Ô3GÐHX×H\ÑH\Ð]`×]dÑ]dÐekÓ]lÓHmÓ3nÑoÖpñ ñ 	œ,›.¨>Õ9¸4¿:¹:ÀdÐST¸:Ó;UÐX\Õ;\Ö]øÜ”Y¤
Ð+ô Úðús   ŒB&B4 Â4CÃCc               ó   € V ^8„  d   QhRR/# )r   r	   zdict | Noner
   )r   s   "r   r   r   A   s   € ÷ xñ x Kñ xr   c                ó    € \        V \        4      '       g   R# RV P                  R4      RV P                  R4      RV P                  R4      RJ /# )z:The parts of an install record an update check depends on.NÚsourceÚrevisionÚpinnedT)Ú
isinstancer   r3   )Úrecords   &r   r2   r2   A   sK   € ä�fœd×#Ò#ÙØ�f—j‘j Ó*¨J¸¿
¹
À:Ó8NÐPXÐZ`×ZdÑZdÐemÓZnÐrvÐZvÐwÐwr   c               ó    € V ^8„  d   QhRRRR/# )r   Úinstall_metadatar   r	   zdict[str, str]r
   )r   s   "r   r   r   H   s   € ÷ ñ ¨ð °.ñ r   c                ó’  € ^ RI p VP                  \        4       P                  RR7      4      p/ p\        T\        4      '       d   TMR Fß  p\        T\        4      '       d,   TP                  R4      R8w  g   TP                  R4      RJd   KF  \        T P                  TP                  R4      4      4      pT'       g   Ky  TR	,          '       d   KŠ  YTP                  R
4      8X  g   K¡  TP                  R4      '       g   Kº  \        TR,          4      T\        TR,          4      &   Ká  	  T#   \        \
        3 d    / u # i ; i)aV  ``{plugin name: what the update moves to}`` (a commit or a feed version) for git installs the last
check found behind. A result is dropped once the install it was checked against changed (updated,
reinstalled from another source, or pinned with ``--ref``), so Desktop never offers an update that
already landed or one ``update`` would refuse.Nz	utf-8-sig©ÚencodingÚclassÚgitÚupdate_availableTr+   rA   r*   Úlatestr
   )r.   Úloadsr   Ú	read_textr6   r8   rB   r$   r   r3   r2   Ústr)rE   r.   r9   Úoutr;   Úcurrents   &     r   Úcached_git_updatesrR   H   s
  € ó
 ðØ�z‰zœ-›/×3Ñ3¸[Ð3ÓIÓJˆð €CÜ! $¬×-Ò-‰t°2Ò5ˆÜ˜#œt×$Ò$¨¯©°Ó(8¸EÔ(AÀSÇWÁWÐM_ÓE`ÐhlÓElÙÜ&Ð'7×';Ñ';¸C¿G¹GÀF»OÓ'LÓMˆß‰7˜7 8×,Ö,°¿G¹GÐDUÓ<VÖ1VÐ[^×[bÑ[bÐck×[lÔ[lÜ$'¨¨H­Ó$6ˆC”�C˜•KÓ Ó!ñ 6ð €Jøô ”ZÐ ô ØŠ	ðús   †)D0 Ä0EÅEc               ó   € V ^8„  d   QhRR/# r   r
   )r   s   "r   r   r   ]   s   € ÷ ñ �dñ r   c                 óT   € \        4       P                  p V P                  RRR7       V # )u8   The markers dir, created on demand â€” WRITE paths only.T)ÚparentsÚexist_ok)r   r   Úmkdir)Úds    r   r4   r4   ]   s$   € ä‹×Ñ€AØ‡G�G�D 4€GÔ(Ø€Hr   c               ó    € V ^8„  d   QhRRRR/# )r   Ú
config_getúCallable | Noner	   Úfloatr
   )r   s   "r   r   r   d   s   € ÷ ñ  _ð Àñ r   c                óÖ   € V f   \         p  V ! RR4      pTf   \        #  \        T4      p\        RT4      #   \         d
    \        u # i ; i  \        \
        3 d
    \        u # i ; i)z8plugins.auto_update_check_hours; 0 disables; default 24.ÚpluginsÚauto_update_check_hoursg        )Ú_default_config_getÚ	ExceptionÚ_DEFAULT_INTERVAL_HOURSr\   r7   r8   Úmax)rZ   ÚvalueÚhourss   &  r   Úcheck_interval_hoursrf   d   sz   € àÒÜ(ˆ
ð'Ù˜9Ð&?Ó@ˆð ‚}Ü&Ð&ð'Ü�e“ˆô ˆs�E‹?Ðøô ô 'Ü&Ò&ð'ûô ”zÐ"ô 'Ü&Ò&ð'ús    Œ	7  A ·AÁ
AÁA(Á'A(c               ó    € V ^8„  d   QhRRRR/# )r   rZ   r[   r	   Úboolr
   )r   s   "r   r   r   u   s   € ÷ ñ  ?ð ¸dñ r   c                ó`   € V f   \         p  \        V ! RR4      4      #   \         d     R# i ; i)Nr^   Ú
auto_applyF)r`   rh   ra   )rZ   s   &r   Úauto_apply_enabledrk   u   s6   € ØÒÜ(ˆ
ðÜ‘J˜y¨,Ó7Ó8Ð8øÜô Úðús   Œ ž-¬-c               ó    € V ^8„  d   QhRRRR/# )r   ÚsectionrO   Úkeyr
   )r   s   "r   r   r   ~   s   € ÷ ñ  ð ¨3ñ r   c                óX   €  ^ RI HpHp V! V! 4       WRR7      #   \         d     R# i ; i)é    )Úcfg_getÚload_config_readonlyN)Údefault)Úhermes_cli.configrq   rr   ra   )rm   rn   rq   rr   s   &&  r   r`   r`   ~   s/   € ðßCáÑ+Ó-¨wÀTÔJÐJøÜô Úðús   ‚ š)¨)c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   ÚnowúOptional[float]Úinterval_hoursrZ   r[   r	   rh   r
   )r   s   "r   r   r   ‡   s*   € ÷ 1ñ 1�?ð 1¸?ð 1Ø)ð1Ø59ñ1r   c                óú   € Vf   \        V4      pV^ 8:  d   R# V f   \        P                  ! 4       MT p \        4       p VP                  4       P                  pY,
          TR,          8¬  #   \
         d     R# i ; i)z0The clock gate: last-run marker vs the interval.FTi  )rf   Útimer   ÚstatÚst_mtimer6   )rv   rx   rZ   ÚmarkerÚlasts   &&&  r   Ú	check_duer   ‡   su   € ð ÒÜ-¨jÓ9ˆØ˜ÔÙØšŒ$�)Š)Œ+¨#€CÜ‹^€FðØ�{‰{‹}×%Ñ%ˆð �J˜>¨DÕ0Ñ0Ð0øô ô Úðús   ¿A+ Á+A:Á9A:Úapply_updates_fnÚlogrZ   rv   c               ó0   € V ^8„  d   QhRRRRRRRRR	R
RR/# )r   Úrun_checks_fnúCallable[..., list]r   r   r€   úOptional[Callable[[str], None]]rZ   r[   rv   rw   r	   úOptional[list]r
   )r   s   "r   r   r   �   sF   € ÷ !ñ !à&ð!ð ð!ð 6ð	!ð  ð!ð 
ð!ð ñ!r   c                ó>  € ^ RI pVf   VP                  \        4      p\        WTR7      '       g   R# \        P                  RR7      '       g   VP                  R4       R#  \        V VVVVR7      \        P                  4        #   \        P                  4        i ; i)uÝ   One cadence tick: gate â†’ check â†’ receipt â†’ (opt-in) apply.

Returns the check results, or None when not due / disabled / another
tick is already in flight. NEVER raises â€” a cadence failure is
logged, never fatal.
N)rv   rZ   F)Úblockingu7   plugin update check already in flight â€” skipping tick)rƒ   r   r€   r�   rZ   )	ÚloggingÚ	getLoggerÚ__name__r   Ú
_tick_lockÚacquireÚdebugÚ_run_check_lockedÚrelease)rƒ   r   r€   r�   rZ   rv   r‰   s   $$$$$$ r   Úrun_scheduled_checkr‘   �   s…   € ó à
‚{Ø×Ñ¤Ó)ˆÜ˜×4Ó4ÙÜ×Ñ uÐ×-Ò-Ø�	‰	ÐKÔLÙð	Ü Ø'Ø#Ø-ØØ!ô
ô 	×ÑÕøŒ
×ÑÕús   Á"B ÂBc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   rƒ   r„   r   r   r€   r…   rZ   r[   r	   r$   r
   )r   s   "r   r   r   Á   sC   € ÷ Gñ Gà&ðGð ðGð 6ð	Gð  ðGð 
ñGr   c                ór  € R pRp/ p \        V4      pV ! V4      pV'       d   \        W‡4        ^ RIHp	 V	P                  R4      p
V	P                  V4       V'       d   V	P                  V4       V Uu. uF  p\        VRR4      R J g   K  VNK  	  ppT	P                  V'       g   R	MV'       d   R
MRV'       d   ^ M^V
R7       V Uu. uF  p\        VRR4      R J g   K  VNK  	  ppV Uu. uF  p\        VRR4      '       g   K  VNK  	  ppV'       d+   RP                  R V 4       4      pVP                  RV4       V'       d+   RP                  R V 4       4      pVP                  RV4       V'       dJ   V'       dB   \        V4      '       d1   V F*  p\        VRR4      R8X  g   K   V! VP                  4       K,  	   \#        4       R,          pVP%                  \'        \)        \*        P*                  ! 4       4      4      RR7       V#   \         d    RpTP                  TR R7       . pRp ELi ; iu upi   \         d    TP                  RR R7        ELœi ; iu upi u upi   \        \         3 d$    TP                  RTP                  R R7        EK  i ; i  \,         d     T# i ; i)TÚ zplugin update check failed)Úexc_infoF)Úreceiptzplugin-checkrK   NÚfailedzupdates-availableÚok)Ú	exit_codeÚtokenz!plugin-check receipt write failedÚneeds_fixingz, c              3  ó8   "  € T F  qP                   x € K  	  R # 5i©N©r+   ©Ú.0r:   s   & r   Ú	<genexpr>Ú$_run_check_locked.<locals>.<genexpr>è   s   é € Ð2©' QŸ&ž&«'ùó   ‚uf   plugin updates available: %s â€” run `hermes plugins check-updates` and `hermes plugins update <name>`c              3  ó8   "  € T F  qP                   x € K  	  R # 5ir�   rž   rŸ   s   & r   r¡   r¢   ï   s   é € Ð7©, QŸ&ž&«,ùr£   um   plugin update_url mismatches need attention: %s â€” run `hermes plugins trust-update-url <name>` after reviewÚklassrJ   zauto-apply of %s failedr   zutf-8rG   )r!   ra   Úwarningr<   Úpmr–   ÚbeginÚrecord_plugin_checksÚrecord_warningÚgetattrÚfinalizerŽ   ÚjoinÚinfork   r+   Ú
SystemExitr4   Ú
write_textrO   Úintrz   r6   )rƒ   r   r€   r�   rZ   Úcheck_okr¦   r%   r#   r–   rš   r:   Úupdatesr›   Únamesr}   s   $$$$$           r   r�   r�   Á   s‹  € ð €HØ€GØÐðÜ,¨[Ó9ÐÙ Ó,ˆ÷ Ü˜WÔ7ð
FÝØ—‘˜nÓ-ˆØ×$Ñ$ WÔ-ßØ×"Ñ" 7Ô+Ù%ÓV™g˜¬°Ð4FÈÓ)MÐQUÐ)U—1�1™gˆÐVØ×Ñ¯™ÏgÑ7JÐ[_ß(0¡1°a¸uð 	ô 	Fñ "ÓR™'�Q¤W¨QÐ0BÀDÓ%IÈTÐ%Q�qˆq™'€GÐRÙ&ÓK™w˜!¬'°!°^ÀT×*J—A�A™w€LÐKßØ—	‘	Ñ2©'Ó2Ó2ˆØ�‰ð1àô	
÷
 Ø—	‘	Ñ7©,Ó7Ó7ˆØ�‰ðDàô	
÷ ŸGÔ(:¸:×(FÒ(FÛˆAÜ�q˜' 2Ó&¨%Ö/ðRÙ$ Q§V¡VÖ,ñ ðÜ“ *Õ,ˆØ×Ñœ#œc¤$§)¢)£+Ó.Ó/¸'ÐÔBð €Nøôs ô Ø.ˆØ�‰�G dˆÔ+ØˆØ‹ð	üò Wøô ô FØ�	‰	Ð5Àˆ	×EðFüò SùÚKøô0 "¤:Ð.ô RØ—K‘KÐ 9¸1¿6¹6ÈD�K×QÐQðRûô ô ØØ€Nðús‰   ˆH ¯/I ÁI Á4H<ÂH<ÂI Â1
I Â<
I Ã
I&Ã"I&Ã.I+ÄI+Æ/I0ÇA	J' È$H9È8H9È<I ÉI#É"I#É0/J$Ê#J$Ê'J6Ê5J6rƒ   r   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   rƒ   zOptional[Callable[..., list]]r€   r…   r   zOptional[Path]rv   rw   r	   r†   r
   )r   s   "r   r   r     s<   € ÷ ,ñ ,à0ð,ð 6ð,ð  ð	,ð 
ð,ð ñ,r   c                ó¶   € Vf   ^ RI Hp VP                  4       pV f	   ^ RIHp Tp Vf!   ^ RI Hp ^ RIHp V! VP                  RR7      p\        V VVVVR7      # )u}  The tick every gateway boot / housekeeping pass calls.

Fills in the REAL seams ``run_scheduled_check`` leaves injectable:
the same read-only ``plugins_updates.run_checks`` the manual
``hermes plugins check-updates`` uses (urllib feed fetch, git
ls-remote, PyPI latest), the real plugins dir, and the manual
``hermes plugins update <name>`` flow as the opt-in apply path â€”
auto-apply rides the identical security/consent/scan pipeline.

Returns the check results, or None when not due / disabled. Due-gated
by ``plugins.auto_update_check_hours`` (0 disables); a network error
costs one warning and a stamped marker â€” never an apply.
)Úplugins_cmd)Ú
run_checks)ÚpartialF)Úinteractive)rƒ   r   r€   r�   rv   )	Ú
hermes_clir·   Ú_plugins_dirÚhermes_cli.plugins_updatesr¸   Ú	functoolsr¹   Ú
cmd_updater‘   )rƒ   r€   r   r�   rv   r·   r¸   r¹   s   $$$$$   r   Úmaybe_run_gateway_checkrÀ     sf   € ð* ÒÝ*à!×.Ñ.Ó0ˆØÒõ
 	:à"ˆØÒÝ*å%Ù" ;×#9Ñ#9ÀuÔMÐÜØ#ØØ)ØØôð r   r�   )NNN)Ú__doc__Ú
__future__r   Ú	threadingrz   Úpathlibr   Útypingr   r   r   rb   r   r   r!   r<   r2   rR   r4   rf   rk   r`   r   ÚLockrŒ   r‘   r�   rÀ   r
   r   r   Ú<module>rÇ      sæ   ðñ
õ #ã Û Ý ß %à%€ØÐ õ9õ2õ
*õõ&xõõ*÷÷"õ÷1ð& �^Š^Ó€
ð!ð 9=ð	!ð
 	ð!ð #'ð!ð  ÷!ðHGð #'÷Gð\,à37ð,ð 9=ð,ð #'ð	,ð
 	ð,ð  ÷,ñ ,r   