+
    lHàjm,  ã                   ó€  € R t ^ RIt^ RIt^ RIHt ^ RIHtHtHt ^ RIH	t	H
t
 ^ RIHtHtHtHtHtHt ^ RIHt ^ RIHt ]P,                  ! R4      tR	 tR
 R ltR R lt]! 0 R*m4      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 lt$R R lt%R R!/R" R# llt&R$ R% lt'R& R' lt(R+R( R) llt)R# ),z»Official optional-skill provenance: hub-lock backfill and restore. Profile-scoped paths and
patchable helpers resolve through ``_ss()`` at call time so ``tools.skills_sync`` patches work.N)Úsuppress)ÚdatetimeÚtimezoneÚUTC)ÚPathÚPurePosixPath)ÚDictÚIteratorÚListÚOptionalÚSetÚTuple)Úis_excluded_skill_path)Úatomic_write_textztools.skills_syncc                 ó   € ^ RI Hp  V # )zYLive ``tools.skills_sync`` module (imported lazily: it imports helpers from this module).©Úskills_sync)Útoolsr   r   s    Ú?/home/ubuntu/.hermes/hermes-agent/tools/skills_sync_optional.pyÚ_ssr      s   € å!ØÐó    c                ó0   € V ^8„  d   QhR\         R\        /# )é   Ú	directoryÚreturn©r   Ústr)Úformats   "r   Ú__annotate__r      s   € ÷ )ñ )œTð )¤cñ )r   c                ót   €  ^ RI Hp V! V 4      #   \         d    \        4       P	                  T 4      u # i ; i)zYHub-lock hash style; provenance metadata only, so fall back to local MD5 sans guard deps.)Úcontent_hash)Útools.skills_guardr    Ú	Exceptionr   Údir_hash)r   r    s   & r   Ú_content_hashr$      s5   € ð)Ý3Ù˜IÓ&Ð&øÜô )Ü‹u�~‰~˜iÓ(Ò(ð)ús   ‚ �$7¶7c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   ÚpathÚbaser   r   )r   s   "r   r   r       s!   € ÷ ñ ¤ð ¬Tð ´cñ r   c                ó.  € \        V P                  V4      P                  4       ;p4      pVP                   Uu. uF  qDR9  g   K  VNK  	  ppVP	                  4       '       g   V'       d   RV9   d   \        RV 24      hRP                  V4      # u upi )zANormalized relative POSIX path; rejects traversal/absolute paths.z..zUnsafe optional skill path: Ú/>   Ú Ú.)r   Úrelative_toÚas_posixÚpartsÚis_absoluteÚ
ValueErrorÚjoin)r&   r'   ÚposixÚpureÚpartr.   s   &&    r   Ú_safe_rel_install_pathr5       s‚   € ä $×"2Ñ"2°4Ó"8×"AÑ"AÓ"CÐC˜ÓD€DØ"ŸjšjÓB™j�d¸	Ñ,A�TˆT™j€EÐBØ×Ñ×Ò§¨$°%¬-ÜÐ7¸°wÐ?Ó@Ð@Ø�8‰8�E‹?Ðùò Cs   ¹BÁBc                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   r&   Ú	skill_dirr   )r   Úbool)r   s   "r   r   r   .   s&   € ÷ Qñ QœDð Q¬Tð Q´dñ Qr   c                ó–  € V P                  V4      p\        ;QJ d)    R VP                  RR  4       F  '       g   K   RM	  RM! R VP                  RR  4       4      '       d   R# V P                  \        9   d   V P                  4       '       d   R# V P                  R9   ;'       d     V P                  R4      P                  4       # )a  Whether a skill-relative path is disposable Python/tool runtime state.

Install prefixes may themselves contain a cache directory name. Legacy
sibling bytecode is ignored only alongside its source; source-less .pyc
files can be deliberately shipped or user-owned content.
c              3   ó2   "  € T F  q\         9   x € K  	  R # 5i)N)Ú_RUNTIME_CACHE_DIRS)Ú.0r4   s   & r   Ú	<genexpr>Ú$_is_runtime_cache.<locals>.<genexpr>6   s   é € Ð
GÑ3F¨4Ô&Ö&Ó3Fùs   ‚NTFz.pyéÿÿÿÿ>   ú.pycú.pyo)	r,   Úanyr.   Únamer;   Úis_dirÚsuffixÚwith_suffixÚis_file)r&   r7   Úrelatives   && r   Ú_is_runtime_cacherI   .   s”   € ð ×Ñ 	Ó*€Hß
ƒsÑ
G°8·>±>À#À2Ñ3FÓ
G‡s‡s‚sÑ
G°8·>±>À#À2Ñ3FÓ
G×GÒGÙØ‡y�yÔ'Ô'¨D¯K©K¯MªMÙØ�;‰;Ð*Ñ*×PÐP¨t×/?Ñ/?ÀÓ/F×/NÑ/NÓ/PÐPr   c                óh   € V ^8„  d   QhR\         R\        \         ,          R\        \         ,          /# )r   r   Únamesr   )r   Úlist)r   s   "r   r   r   =   s.   € ÷ Lñ L¤Sð L´´cµð L¼tÄC½yñ Lr   c                óz   € \        V 4      pV Uu. uF  p\        W#,          V4      '       g   K  VNK!  	  up# u upi )zEcopytree callback: don't seed generated caches into managed packages.)r   rI   )r   rK   ÚrootrC   s   &&  r   Ú_ignore_runtime_cacherO   =   s1   € ä�	‹?€DÙ"ÓK™U�TÔ&7¸½ÀT×&J�DˆD™UÑKÐKùÒKs   �8¯8c                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r   r7   r   )r   rL   r   )r   s   "r   r   r   C   s"   € ÷ Dñ D¤ð D¬¬c­ñ Dr   c                óð   € \        V P                  R4      4       Uu. uFM  p\        W4      '       d   K  VP                  4       '       g   K.  VP	                  V 4      P                  4       NKO  	  up# u upi )zKList package files for provenance/diff, excluding generated runtime caches.Ú*)ÚsortedÚrglobrI   rG   r,   r-   )r7   Úfs   & r   Ú_skill_file_listrV   C   sd   € ä9?À	ÇÁÐPSÓ@TÔ9Uó DÑ9U°AÜ$ Q×2ô 0Ø78·y±y·{ô 0ˆA�M‰M˜)Ó$×-Ñ-Ö/Ñ9Uñ Dð Dùò Ds   �A3µA3Á#A3c                ó:   € V ^8„  d   QhR\         \        ,          /# ©r   r   )r   Údict)r   s   "r   r   r   I   s   € ÷ ñ œ¤�ñ r   c                 óæ   €  \         P                  ! \        4       P                  4       R,          R,          P	                  RR7      4      #   \
        \         P                  \        3 d     R# i ; i)z;Parse the skills-hub lock; None when missing or unreadable.ú.hubú	lock.jsonz	utf-8-sig)ÚencodingN)ÚjsonÚloadsr   Ú_skills_dirÚ	read_textÚFileNotFoundErrorÚJSONDecodeErrorÚOSError© r   r   Ú_load_hub_lockrf   I   sY   € ðÜ�zŠzœ3›5×,Ñ,Ó.°Õ7¸+ÕE×PÑPÐZeÐPÓfÓgÐgøÜœt×3Ñ3´WÐ=ô Úðús   ‚A	A Á A0Á/A0c                ó\   € V ^8„  d   QhR\         \        ,          R\        \        ,          /# )r   Údatar   )r   rY   rL   )r   s   "r   r   r   Q   s&   € ÷ ^ñ ^œH¤T�Nð ^¬t´D­zñ ^r   c                 óÂ   € T ;'       g    / P                  R 4      ;'       g    / P                  4        Uu. uF  p\        V\        4      '       g   K  VNK  	  up# u upi )Ú	installed)ÚgetÚvaluesÚ
isinstancerY   )rh   Úes   & r   Ú_hub_lock_entriesro   Q   sK   € ØŸ˜ ×(Ñ(¨Ó5×;Ð;¸×CÑCÔEÓ]ÑE�!ÌÐTUÔW[×I\�AˆAÑEÑ]Ð]ùÒ]s   ¶AÁAc                ó:   € V ^8„  d   QhR\         \        ,          /# rX   )Úsetr   )r   s   "r   r   r   U   s   € ÷ uñ u¤¤S¥ñ ur   c                 óÀ   € \        \        4       4       U u0 uF<  q P                  R4      '       g   K  \        V R,          4      P	                  R4      kK>  	  up # u up i )z·Hub-lock install paths as POSIX strings. Hub-installed skills are owned by the hub: rename
recovery must not move them even when content matches a bundled origin hash (dangling lock).Úinstall_pathr)   )ro   rf   rk   r   Ústrip)rn   s    r   Ú_read_hub_install_pathsru   U   sK   € ô 8IÌÓIYÔ7ZÓtÑ7Z°!×^cÑ^cÐdr×^sÔ-ŒC��.Õ!Ó"×(Ñ(¨Ö-Ñ7ZÑtÐtùÒts
   –A³%Ac          
      ó~   € V ^8„  d   QhR\         R\        R\        \        \         \         \        3,          ,          /# )r   Úoptional_dirÚroot_relativer   )r   r8   r	   Útupler   )r   s   "r   r   r   [   s;   € ÷ 	`ñ 	`¬ð 	`Äð 	`ÌÔRWÔX\Ô^bÔdgÐXgÕRhÕIiñ 	`r   c             #  óŠ  "  € \        V P                  R4      4       Ff  pV'       d$   \        VP                  V 4      V R7      '       d   M\        V4      '       d   KA   W"P                  \        VP                  V 4      3x € Kh  	  R#   \         d-   p\        P                  RTP                  T4        Rp?Kž  Rp?ii ; i5i)zOYield ``(skill_md, src, install_path)`` for every safe official optional skill.úSKILL.md)rN   z/Skipping optional skill with unsafe path %s: %sN)	rS   rT   r   r,   Úparentr5   r0   ÚloggerÚdebug)rw   rx   Úskill_mdrn   s   &$  r   Ú_iter_optional_skillsr€   [   s˜   é € ä˜<×-Ñ-¨jÓ9Ö:ˆç ô # 8×#7Ñ#7¸Ó#EÈL×YÔYÜ&<¸X×&FÒ&FÙð	`ØŸO™OÔ-CÀHÇOÁOÐUaÓ-bÐbÔbó ;øô ô 	`Ü�L‰LÐJÈHÏOÉOÐ]^×_Ò_ûð	`üs0   ‚ACÁ$B	ÂCÂ	C Â!B;Â5CÂ;C Ã Cc                ór   € V ^8„  d   QhR\         \        \        \        \        \        3,          3,          /# rX   )rY   r   ry   r   )r   s   "r   r   r   g   s(   € ÷ 
ñ 
œt¤C¬¬s´C¼¨~Õ)>Ð$>Õ?ñ 
r   c                 ó
  € \        4       p V P                  4       p/ pVP                  4       '       dQ   \        VRR7       F?  w  r4pVP                  WT3pV;W$P                  &   W P                  W4P                  4      &   KA  	  V# )z¤Official optional skills keyed by BOTH folder name and frontmatter name (hub-lock slug or
user-facing name). Values are ``(folder_name, install_path, source_dir)``.T©rx   )r   Ú_get_optional_dirÚexistsr€   rC   Úread_skill_name)Ússrw   Úindexr   Úsrcrs   Úvalues          r   Ú_optional_skill_indexr‹   g   s|   € ô 
‹€BØ×'Ñ'Ó)€LØ.0€EØ×Ñ×ÒÜ+@ÀÐ]a×+bÑ'ˆH˜<Ø—X‘X˜|Ð1ˆEØNSÐSˆE—(‘(‰O˜e×$6Ñ$6°xÇÁÓ$JÓKñ ,cð €Lr   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   r&   Úbackup_rootr   r   )r   s   "r   r   r   t   s!   € ÷ 	ñ 	¤$ð 	´Tð 	¼cñ 	r   c                ó6  € \        4       pV P                  VP                  4       4      pW,          ^ rTVP                  4       '       d2   V^,          pW,          P	                  VP
                   RV 24      pKG  VP                  W4       VP                  4       # )zLMove an existing skill directory into a restore backup, preserving rel path.Ú-)r   r,   r`   r…   Ú	with_namerC   Ú	_move_dirr-   )r&   r�   r‡   ÚrelÚtargetrE   s   &&    r   Ú_move_to_restore_backupr”   t   sx   € ä	‹€BØ
×
Ñ
˜2Ÿ>™>Ó+Ó
,€CØ Õ&¨ˆFØ
�-‰-�/Š/Ø�!�ˆØÕ#×.Ñ.°#·(±(°¸1¸V¸HÐ/EÓFŠØ‡L�L�ÔØ�<‰<‹>Ðr   ÚrestoreFc                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   rC   r•   r   )r   r8   rY   )r   s   "r   r   r   €   s!   € ÷ $=ñ $=¬#ð $=¼4ð $=ÌDñ $=r   c               ó"  € \        4       p\        4       pV'       d.   V R9   d'   \        \        VP	                  4       4      R R7      pM+W9   d   W0,          .pMV'       d   RV  2MRpRRRVR. R	. R
. /# . p. p\
        P                  ! \        4      P                  R4      pVP                  4       R,          RV 2,          p	V'       d   TM.  EF‘  w  r«pVP                  4       \        VP                  R4      !  ,          pVP                  4       ;'       d$    VP                  V4      VP                  V4      8H  pW¢P                  VR,          V
4      0pVP                  RR7       F  pVP                   pVV8w  g   K  VP                  4       '       g   K0  VP"                  V
8X  g$   VP                  VVP"                  4      V9   g   Kd  VP%                  \'        VV	4      4       K�  	  VP                  4       '       d#   V'       g   VP%                  \'        WÙ4      4       VP                  4       '       d   EKo  VP)                  WÍ4       VP%                  V
4       EK”  	  RRRRRTR	\+        RR7      R
TRV'       d   \-        V	4      /# R/# )zäRestore one or all official optional skills from repo source. ``restore=False`` only
backfills exact-match provenance; ``restore=True`` also backs up matching active copies
and copies the official source into its canonical path.c                 ó   € V ^,          # )é   re   )Úitems   &r   Ú<lambda>Ú1restore_official_optional_skill.<locals>.<lambda>‡   s   € ¸tÀA¾wr   )Úkeyz#Official optional skill not found: z,No official optional skills directory found.ÚokFÚmessageÚrestoredÚ
backfilledÚ	backed_upz%Y%m%d-%H%M%Sz.restore-backupszofficial-optional-r)   r{   T)Úsortz(Official optional skill repair complete.)ÚquietÚ
backup_dirr*   >   rR   Úall)r   r‹   rS   rq   rl   r   Únowr   Ústrftimer`   r   Úsplitr…   r#   r†   Ú_iter_active_skill_mdsr|   rC   Úappendr”   Ú	_copy_dirÚ_backfill_optional_provenancer   )rC   r•   r‡   rˆ   ÚtargetsrŸ   r    r¢   Ú	timestampr�   Úfolder_namers   r‰   ÚdestÚcanonical_okrK   ÚmdÚmatchs   &$                r   Úrestore_official_optional_skillrµ   €   s*  € ô 
‹€BÜ!Ó#€Eß�˜Ô%Üœ˜UŸ\™\›^Ó,Ñ2FÔG‰Ø	ŒØ•;�-‰çBGÐ7¸°vÑ>ÐM{ˆØ�e˜Y¨°¸RÀÈrÐS^Ð`bÐcÐcØ€HØ€IÜ—’œSÓ!×*Ñ*¨?Ó;€IØ—.‘.Ó"Ð%7Õ7Ð<NÈyÈkÐ:ZÕZ€Kß5<©'À"Ó*DÑ&ˆ 3Ø�~‰~Ó¤$¨×(:Ñ(:¸3Ó(?Ñ"@Õ@ˆØ—{‘{“}×NÐN¨¯©°TÓ):¸b¿k¹kÈ#Ó>NÑ)Nˆð ×0Ñ0°°zÕ1AÀ;ÓOÐPˆØ×+Ñ+°Ð+Ö6ˆBØ—I‘IˆEØ˜Ž} §¡§¤Ø—J‘J +Ô-°×1CÑ1CÀBÈÏ
É
Ó1SÐW\Ö1\Ø× Ñ Ô!8¸ÀÓ!LÖMñ	 7ð
 �;‰;�=Š=§Ø×ÑÔ4°TÓGÔHØ�{‰{�}�}Ø�L‰L˜Ô#Ø�O‰O˜K×(ñ +Eð" 	ˆd�IÐIÈ:ÐW_ØÔ3¸$Ô?ÀÈiØ¯)”c˜+Ó&ð=ð =ð :<ð=ð =r   c                ó\   € V ^8„  d   QhR\         \        \        \        ,          3,          /# rX   )rY   r   rL   r   )r   s   "r   r   r   §   s    € ÷ 
ñ 
¬T´#´t¼Dµz°/Õ-Bñ 
r   c                 óÊ  € \        4       p / pV P                  4       P                  4       pV P                  4        F�  p\	        \
        \        4      ;_uu_ 4        VP                  P                  4       P                  V4       VP                  VP                  P                  . 4      P                  VP                  4       RRR4       K’  	  V#   + '       g   i     K§  ; i)zˆInstalled skills by directory name in one active-tree scan, skipping anything that
resolves outside the skills tree (symlinks/external).N)r   r`   Úresolverª   r   rd   r0   r|   r,   Ú
setdefaultrC   r«   )r‡   rˆ   rN   r   s       r   Ú#_index_installed_skill_dirs_by_namerº   §   s¤   € ô 
‹€BØ#%€EØ�>‰>Ó×#Ñ#Ó%€DØ×-Ñ-Ö/ˆÜ”gœz×*Õ*Ø�O‰O×#Ñ#Ó%×1Ñ1°$Ô7Ø×Ñ˜XŸ_™_×1Ñ1°2Ó6×=Ñ=¸h¿o¹oÔN÷ +Ñ*ñ 0ð €L÷ +×*Ð*ús   ÁA)CÃC"c          	      ó¬   € V ^8„  d   QhR\         R\        \         \        \        ,          3,          R\        \
        \        \         3,          ,          /# )r   Úsrc_namerˆ   r   )r   rY   rL   r   r   ry   )r   s   "r   r   r   ´   s?   € ÷ 
ñ 
œcð 
¬$¬s´D¼µJ¨Õ*?ð 
ÄHÌUÔSWÔY\ÐS\ÕM]ÕD^ñ 
r   c                ó  € \        VP                  V . 4      ;p4      ^8w  d   R#  V^ ,          \        V^ ,          \        4       P	                  4       4      3#   \
         d*   p\        P                  RT^ ,          T4        Rp?R# Rp?ii ; i)zí``(dest, install_path)`` of a UNIQUE same-directory-name match, else None: the active
tree may hold a skill under a DIFFERENT category than the repo (upstream reorganized,
installed copy kept its place); ambiguity gives no basis to pick.Nz(Skipping relocated optional skill %s: %s)Úlenrk   r5   r   r`   r0   r}   r~   )r¼   rˆ   Ú
candidatesrn   s   &&  r   Ú_relocated_destrÀ   ´   sx   € ô ˜Ÿ™ 8¨RÓ0Ð0ˆ:Ó1°QÔ6ÙðØ˜!�}Ô4°ZÀµ]ÄCÃE×DUÑDUÓDWÓXÐXÐXøÜô Ü�‰Ð?ÀÈAÅÐPQÔRÝûðús   ¦1A ÁBÁ#BÂBc                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r   r¤   r   )r8   rL   r   )r   s   "r   r   r   Á   s   € ÷ *ñ *¬ð *¼$¼s½)ñ *r   c                ó€  € \        4       pVP                  4       pVP                  4       '       g   . # \        4       pVf   R^R/ /pVP	                  R/ 4      p\        V4       Uu0 uF  qUP                  R4      kK  	  pp. pRp\        VRR7       EFR  w  ršpV
P                  pWÄ9   g   W¶9   d   K!  VP                  4       \        VP                  R4      !  ,          pVP                  4       '       g/   Vf   \        4       p\        V
P                  V4      ;pf   KŽ  Vw  rÛW¶9   g&   VP                  V4      VP                  V
4      8w  d   K¿  \         P"                  ! \$        4      P'                  4       pRR	R
RV 2RRRRR\)        V4      RVR\+        V4      RRR/RVRV/
WL&   VP-                  V4       VP/                  V4       V '       d   EKC  \1        RV R24       EKU  	  V'       dI   \3        VP                  4       R,          R,          R\4        P6                  ! V^RR7      R,           R7       V# u upi )zäMark already-present official optional skills as hub-installed: formerly bundled (or
hand-copied) skills now under optional-skills/ get official provenance when byte-identical
to the source; modified/local skills are left alone.NÚversionrj   rs   Frƒ   r)   ÚsourceÚofficialÚ
identifierz	official/Útrust_levelÚbuiltinÚscan_verdictr¡   r    ÚfilesÚmetadataÚbackfilled_fromzoptional-skillsÚinstalled_atÚ
updated_atz  = z* (official optional provenance backfilled)r[   r\   z.lock_)ÚindentÚensure_asciiÚ
)Ú
tmp_prefixÚcontent)r   r„   r…   rf   r¹   ro   rk   r€   rC   r`   r   r©   rD   rº   rÀ   r#   r   r§   r   Ú	isoformatr$   rV   Úaddr«   Úprintr   r^   Údumps)r¤   r‡   rw   rh   rj   ÚentryÚexisting_pathsr¡   Úinstalled_dir_indexÚ	_skill_mdr‰   rs   Ú	lock_namer±   Úfoundr¯   s   &               r   r­   r­   Á   s  € ô 
‹€BØ×'Ñ'Ó)€LØ×Ñ× Ò Øˆ	ÜÓ€DØ‚|Ø˜1˜k¨2Ð.ˆØ—‘ ¨RÓ0€IÜ=NÈtÔ=TÓUÑ=T°E—i‘i Ö/Ñ=T€NÐUØ€JØ;?ÐÜ(=¸lÐZ_×(`Ð(`Ñ$ˆ	˜Ø—H‘Hˆ	ØÔ! \Ô%CÙØ�~‰~Ó¤$¨×(:Ñ(:¸3Ó(?Ñ"@Õ@ˆØ�{‰{�}Š}Ø"Ò*Ü&IÓ&KÐ#Ü(¨¯©Ð3FÓGÐG�ÒPÙØ!&ÑˆDØÔ)¨R¯[©[¸Ó->À"Ç+Á+ÈcÓBRÔ-RÙÜ—L’L¤Ó%×/Ñ/Ó1ˆ	à�j ,°)¸L¸>Ð0JØ˜9 n°lØœM¨$Ó/°ÀØÔ% dÓ+¨ZÐ:KÐM^Ð9_Ø˜I |°Yð @ˆ	Ñð 	×Ñ˜<Ô(Ø×Ñ˜)Ô$ßŠuÜ�D˜˜Ð#MÐN×Oñ/ )a÷0 Ü˜"Ÿ.™.Ó*¨VÕ3°kÕAÈhÜ"&§*¢*¨T¸!È%Ô"PÐSWÕ"Wõ	YàÐùò= Vs   Á&H;>   Ú__pycache__ú.mypy_cacheú.ruff_cacheú.pytest_cache)F)*Ú__doc__r^   ÚloggingÚ
contextlibr   r   r   r   Úpathlibr   r   Útypingr   r	   r
   r   r   r   Úagent.skill_utilsr   Úutilsr   Ú	getLoggerr}   r   r$   r5   Ú	frozensetr;   rI   rO   rV   rf   ro   ru   r€   r‹   r”   rµ   rº   rÀ   r­   re   r   r   Ú<module>rë      s­   ðñcó Û Ý ß ,Ñ ,ß 'ß =× =å 4Ý #à	×	Ò	Ð.Ó	/€òõ)õñ  Ò ^Ó_Ð õQõLõDõõ^õuõ	`õ
õ	ð$=À%÷ $=õN
õ
÷*ñ *r   