§
    øžyjä  ã                   ó¨  — d Z ddlZddlZddlZddlZddlZddlZddlmZmZ ddl	m
Z
mZ ej        ej        fD ]4Z eed¦  «        r&	 e                     dd¬¦  «         Œ'# eef$ r Y Œ0w xY wŒ5dd	lmZmZmZ dd
lmZ ddlmZmZmZmZmZ ddlm Z   ej!        e"¦  «        Z# e¦   «         Z$e$dz  Z%e%dz  Z&dZ'de
fd„Z(de
fd„Z)dee*         fd„Z+dee*e*f         fd„Z,de-fd„Z.dee*e*f         fd„Z/de
de*de*fd„Z0de
deee*e
f                  fd„Z1de
de
de
fd„Z2de
de*fd „Z3d!e
d"e
de*fd#„Z4de
dee*         fd$„Z5de
de*fd%„Z6dee*ee*e*e
f         f         fd&„Z7d!e
d'e
de*fd(„Z8d)d*œd+e*d,e9de:fd-„Z;dee*ee
         f         fd.„Z<	 d`d/e*d0eee*ee
         f                  dee
         fd1„Z=dad2e9dee*         fd3„Z>dee*         fd4„Z?dee*ee
         f         fd5„Z@d6e*d7e*d8e
d9ee*ee
         f         d:ee*         d2e9dee*         fd;„ZAdad2e9de:fd<„ZBd!e
ddfd=„ZCdad+e*d,e9de:fd>„ZDd7e*d?e*de9fd@„ZEdee:         fdA„ZFd!e
deeeG         ee*         f         fdB„ZHd+e*de:fdC„ZIdDe9de:fdE„ZJde9fdF„ZKdadGe9de:fdH„ZLe"dIk    �rW eMdJ¦  «          eBd)¬K¦  «        ZN eOeNdL         ¦  «        › dM� eOeNdN         ¦  «        › dO�eNdP         › dQ�gZPeNdR         rneNdR         ZQdSZRdT S                    eQdeR…         ¦  «        ZT eOeQ¦  «        eRk    reTdU eOeQ¦  «        eRz
  › dV�z  ZTeP U                     eOeQ¦  «        › dWeT› �¦  «         eNdX         r'eP U                     eOeNdX         ¦  «        › dY�¦  «         eN V                    dZ¦  «        r'eP U                     eOeNdZ         ¦  «        › d[�¦  «          eMd\dT S                    eP¦  «        › d]eNd^         › d_�¦  «         dS dS )bu=  
Skills Sync -- Manifest-based seeding and updating of bundled skills.

Copies bundled skills from the repo's skills/ directory into ~/.hermes/skills/
and uses a manifest to track which skills have been synced and their origin hash.

Manifest format (v2): each line is "skill_name:origin_hash" where origin_hash
is the MD5 of the bundled skill at the time it was last synced to the user dir.
Old v1 manifests (plain names without hashes) are auto-migrated.

Update logic:
  - NEW skills (not in manifest): copied to user dir, origin hash recorded.
  - EXISTING skills (in manifest, present in user dir):
      * If bundled still matches origin hash: no update â†’ skip without reading
        the user copy.
      * If bundled changed and user copy matches origin hash: safe to update.
      * If bundled changed and user copy differs: user customized it â†’ SKIP.
  - DELETED by user (in manifest, absent from user dir): respected, not re-added.
  - REMOVED from bundled (in manifest, gone from repo): cleaned from manifest.

The manifest lives at ~/.hermes/skills/.bundled_manifest.
é    N)ÚdatetimeÚtimezone)ÚPathÚPurePosixPathÚreconfigureúutf-8Úreplace©ÚencodingÚerrors)Úget_bundled_skills_dirÚget_hermes_homeÚget_optional_skills_dir)Úis_excluded_skill_path)ÚDictÚListÚOptionalÚSetÚTuple)Úatomic_replaceÚskillsz.bundled_manifestz.no-bundled-skillsÚreturnc                  ó^   — t          t          t          ¦  «        j        j        dz  ¦  «        S )z°Locate the bundled skills/ directory.

    Checks HERMES_BUNDLED_SKILLS env var first (set by Nix wrapper),
    then falls back to the relative path from this source file.
    r   )r   r   Ú__file__Úparent© ó    ú7/home/ragecks/.hermes/hermes-agent/tools/skills_sync.pyÚ_get_bundled_dirr   F   s#   € õ "¥$¥x¡.¤.Ô"7Ô">ÀÑ"IÑJÔJÐJr   c                  ó^   — t          t          t          ¦  «        j        j        dz  ¦  «        S )z/Locate the official optional-skills/ directory.úoptional-skills)r   r   r   r   r   r   r   Ú_get_optional_dirr"   O   s"   € å"¥4­¡>¤>Ô#8Ô#?ÐBSÑ#SÑTÔTÐTr   c                  ó€  — 	 ddl m} m} n# t          $ r t	          ¦   «         cY S w xY w |¦   «          t	          ¦   «         } | ¦   «         D ]r}|                     d¦  «        D ]Z}t          |¦  «        rŒ|j        }|                     |j	        ¦  «         t          |d¦  «        }|r|                     |¦  «         Œ[Œs|S )zéIndex every skill available in external_dirs by name and frontmatter name.

    Returns a set of skill names that are already provided by external dirs.
    Used to prevent sync_skills from shadowing externally-delegated skills.
    r   )Úget_external_skills_dirsÚ_external_dirs_cache_clearúSKILL.mdÚ )Úagent.skill_utilsr$   r%   ÚImportErrorÚsetÚrglobr   r   ÚaddÚnameÚ_read_skill_name)r$   r%   Úexternal_namesÚext_dirÚskill_mdÚ	skill_dirÚfrontmatter_names          r   Ú_build_external_skill_indexr4   T   s  € ðØZÐZÐZÐZÐZÐZÐZÐZÐZøÝð ð ð Ý‰uŒuˆˆˆðøøøð ÐÑ Ô Ð å"™uœu€NØ+Ð+Ñ-Ô-ð 
5ð 
5ˆØŸš jÑ1Ô1ð 		5ð 		5ˆHÝ% hÑ/Ô/ð ØØ œˆIà×Ò˜yœ~Ñ.Ô.Ð.å/°¸"Ñ=Ô=ÐØð 5Ø×"Ò"Ð#3Ñ4Ô4Ð4øð		5ð Ðs   ‚ ‹&¥&c                  óš  — t                                ¦   «         si S 	 i } t                                d¬¦  «                             ¦   «         D ]e}|                     ¦   «         }|sŒd|v rC|                     d¦  «        \  }}}|                     ¦   «         | |                     ¦   «         <   Œ`d| |<   Œf| S # t          t          f$ r i cY S w xY w)zÑ
    Read the manifest as a dict of {skill_name: origin_hash}.

    Handles both v1 (plain names) and v2 (name:hash) formats.
    v1 entries get an empty hash string which triggers migration on next sync.
    r   ©r   ú:r'   )ÚMANIFEST_FILEÚexistsÚ	read_textÚ
splitlinesÚstripÚ	partitionÚOSErrorÚIOError)ÚresultÚliner-   Ú_Úhash_vals        r   Ú_read_manifestrD   q   sæ   € õ ×ÒÑ!Ô!ð Øˆ	ðØˆÝ!×+Ò+°WÐ+Ñ=Ô=×HÒHÑJÔJð 
	"ð 
	"ˆDØ—:’:‘<”<ˆDØð ØØ�dˆ{ˆ{à$(§N¢N°3Ñ$7Ô$7Ñ!��a˜Ø'/§~¢~Ñ'7Ô'7��t—z’z‘|”|Ñ$Ð$ð  "��t‘�ØˆøÝ•WÐð ð ð Øˆ	ˆ	ˆ	ðøøøs   �BB4 Â4C
Ã	C
c                  óº  — 	 ddl m}   | ¦   «         S # t          $ r¾ t          dz  }|                     ¦   «         st          ¦   «         cY S t          ¦   «         }	 |                     d¬¦  «                             ¦   «         D ]B}|                     ¦   «         }|r*| 	                    d¦  «        s| 
                    |¦  «         ŒCn# t          $ r Y nw xY w|cY S w xY w)u  Built-in skills the curator pruned â€” must NOT be re-seeded on sync.

    Delegates to ``tools.skill_usage`` (single source of truth) and falls back
    to reading ``~/.hermes/skills/.curator_suppressed`` directly if that import
    is unavailable in a packaged/update context.
    r   )Úread_suppressed_namesz.curator_suppressedr   r6   ú#)Útools.skill_usagerF   Ú	ExceptionÚ
SKILLS_DIRr9   r*   r:   r;   r<   Ú
startswithr,   r>   )rF   ÚpathÚnamesrA   s       r   Ú_read_suppressed_namesrN   Œ   s
  € ðØ;Ð;Ð;Ð;Ð;Ð;à$Ð$Ñ&Ô&Ð&øÝð ð ð ÝÐ1Ñ1ˆØ�{Š{‰}Œ}ð 	Ý‘5”5ˆLˆLˆLÝ‘”ˆð	ØŸš°˜Ñ8Ô8×CÒCÑEÔEð $ð $�Ø—z’z‘|”|�Øð $ §¢°Ñ 4Ô 4ð $Ø—I’I˜d‘O”O�Oøð$øõ ð 	ð 	ð 	ØˆDð	øøøàˆˆˆðøøøs:   ‚ ’6CÁ
CÁA+CÃCÃ
CÃCÃCÃCÃCÚentriesc                 ó@  — ddl }t          j                             dd¬¦  «         d                     d„ t          |                      ¦   «         ¦  «        D ¦   «         ¦  «        dz   }	 |                     t          t          j        ¦  «        dd¬	¦  «        \  }}	 t          j
        |d
d¬¦  «        5 }|                     |¦  «         |                     ¦   «          t          j        |                     ¦   «         ¦  «         ddd¦  «         n# 1 swxY w Y   t          |t          ¦  «         dS # t           $ r( 	 t          j        |¦  «         n# t$          $ r Y nw xY w‚ w xY w# t&          $ r.}t(                               dt          |d¬¦  «         Y d}~dS d}~ww xY w)z²Write the manifest file atomically in v2 format (name:hash).

    Uses a temp file + os.replace() to avoid corruption if the process
    crashes or is interrupted mid-write.
    r   NT©ÚparentsÚexist_okÚ
c              3   ó*   K  — | ]\  }}|› d |› �V — ŒdS )r7   Nr   )Ú.0r-   rC   s      r   ú	<genexpr>z"_write_manifest.<locals>.<genexpr>¯   s4   è è € ÐXÐX©n¨d°H˜Ð)Ð)˜xÐ)Ð)ÐXÐXÐXÐXÐXÐXr   z.bundled_manifest_ú.tmp©ÚdirÚprefixÚsuffixÚwr   r6   z&Failed to write skills manifest %s: %s©Úexc_info)Útempfiler8   r   ÚmkdirÚjoinÚsortedÚitemsÚmkstempÚstrÚosÚfdopenÚwriteÚflushÚfsyncÚfilenor   ÚBaseExceptionÚunlinkr>   rI   ÚloggerÚdebug)rO   r`   ÚdataÚfdÚtmp_pathÚfÚes          r   Ú_write_manifestrv   ¦   sú  € ð €O€O€OåÔ×Ò t°dÐÑ;Ô;Ð;Ø�9Š9ÐXÐXÅÀwÇ}Â}ÁÄÑ@WÔ@WÐXÑXÔXÑXÔXÐ[_Ñ_€Dð`Ø×'Ò'Ý•MÔ(Ñ)Ô)Ø'Øð (ñ 
ô 
‰ˆˆHð
	Ý”˜2˜s¨WÐ5Ñ5Ô5ð %¸Ø—’˜‘”�Ø—’‘	”	�	Ý”˜Ÿš™œÑ$Ô$Ð$ð%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %õ ˜8¥]Ñ3Ô3Ð3Ð3Ð3øÝð 	ð 	ð 	ðÝ”	˜(Ñ#Ô#Ð#Ð#øÝð ð ð Ø�ðøøøàð	øøøøõ ð `ð `ð `Ý�ŠÐ=½}ÈaÐZ^ˆÑ_Ô_Ð_Ð_Ð_Ð_Ð_Ð_Ð_øøøøð`øøøss   Á(2E% ÂD0 Â2ADÄD0 ÄDÄD0 ÄDÄD0 Ä0
E"Ä;EÅE"Å
EÅE"ÅEÅE"Å"E% Å%
FÅ/#FÆFr1   Úfallbackc                 óž  — 	 |                       dd¬¦  «        dd…         }n# t          $ r |cY S w xY wd}|                     d¦  «        D ]�}|                     ¦   «         }|dk    r|r nbd	}Œ#|r\|                     d
¦  «        rG|                     dd¦  «        d                              ¦   «                              d¦  «        }|r|c S Œ‚|S )zORead the name field from SKILL.md YAML frontmatter, falling back to *fallback*.r   r	   r
   Ni   FrT   z---Tzname:r7   é   z"')r:   r>   Úsplitr<   rK   )r1   rw   ÚcontentÚin_frontmatterrA   ÚstrippedÚvalues          r   r.   r.   Ç   s  € ðØ×$Ò$¨g¸iÐ$ÑHÔHÈÈ$ÈÔOˆˆøÝð ð ð Øˆˆˆðøøøà€NØ—’˜dÑ#Ô#ð 
ð 
ˆØ—:’:‘<”<ˆØ�uÒÐØð Ø�Ø!ˆNØØð 	˜h×1Ò1°'Ñ:Ô:ð 	Ø—N’N 3¨Ñ*Ô*¨1Ô-×3Ò3Ñ5Ô5×;Ò;¸EÑBÔBˆEØð Ø���øØ€Os   ‚" ¢1°1Úbundled_dirc                 ó  — g }|                       ¦   «         s|S |                      d¦  «        D ]Z}t          |                     | ¦  «        | ¬¦  «        rŒ'|j        }t          ||j        ¦  «        }|                     ||f¦  «         Œ[|S )zz
    Find all SKILL.md files in the bundled directory.
    Returns list of (skill_name, skill_directory_path) tuples.
    r&   ©Úroot)r9   r+   r   Úrelative_tor   r.   r-   Úappend)r   r   r1   r2   Ú
skill_names        r   Ú_discover_bundled_skillsr†   Ü   s§   € ð
 €FØ×ÒÑÔð Øˆà×%Ò% jÑ1Ô1ð /ð /ˆõ
 "Ø× Ò  Ñ-Ô-°Kð
ñ 
ô 
ð 	ð Ø”Oˆ	Ý% h°	´Ñ?Ô?ˆ
Ø�Š�z 9Ð-Ñ.Ô.Ð.Ð.à€Mr   r2   c                 ó@   — |                       |¦  «        }t          |z  S )z 
    Compute the destination path in SKILLS_DIR preserving the category structure.
    e.g., bundled/skills/mlops/axolotl -> ~/.hermes/skills/mlops/axolotl
    )rƒ   rJ   )r2   r   Úrels      r   Ú_compute_relative_destr‰   õ   s"   € ð
 ×
Ò
 Ñ
,Ô
,€CÝ˜ÑÐr   Ú	directoryc                 óÖ  — t          j        ¦   «         }	 t          |                      d¦  «        ¦  «        D ]‡}|                     ¦   «         rq|                     | ¦  «        }|                     t          |¦  «                             d¦  «        ¦  «         |                     | 	                    ¦   «         ¦  «         Œˆn# t          t          f$ r Y nw xY w|                     ¦   «         S )zHCompute a hash of all file contents in a directory for change detection.Ú*r   )ÚhashlibÚmd5rc   r+   Úis_filerƒ   Úupdaterf   ÚencodeÚ
read_bytesr>   r?   Ú	hexdigest)rŠ   ÚhasherÚfpathrˆ   s       r   Ú	_dir_hashr–   þ   sÙ   € åŒ[‰]Œ]€FðÝ˜IŸOšO¨CÑ0Ô0Ñ1Ô1ð 	2ð 	2ˆEØ�}Š}‰Œð 2Ø×'Ò'¨	Ñ2Ô2�Ø—’�c #™hœhŸošo¨gÑ6Ô6Ñ7Ô7Ð7Ø—’˜e×.Ò.Ñ0Ô0Ñ1Ô1Ð1øð		2øõ
 •WÐð ð ð Øˆðøøøà×ÒÑÔÐs   •B*C  Ã CÃCrL   Úbasec                 ó@  — |                       |¦  «        }|                     ¦   «         }t          |¦  «        }d„ |j        D ¦   «         }|                     ¦   «         s|rt          d„ |D ¦   «         ¦  «        rt          d|› �¦  «        ‚d                     |¦  «        S )zLReturn a normalized relative POSIX path, rejecting traversal/absolute paths.c                 ó   — g | ]}|d v¯|‘Œ	S )>   r'   ú.r   ©rV   Úparts     r   ú
<listcomp>z*_safe_rel_install_path.<locals>.<listcomp>  s"   € ÐBÐBÐB�d¨D¸	Ð,AÐ,AˆTÐ,AÐ,AÐ,Ar   c              3   ó"   K  — | ]
}|d k    V — ŒdS )z..Nr   r›   s     r   rW   z)_safe_rel_install_path.<locals>.<genexpr>  s&   è è € Ð-MÐ-M¸t¨d°dªlÐ-MÐ-MÐ-MÐ-MÐ-MÐ-Mr   zUnsafe optional skill path: ú/)rƒ   Úas_posixr   ÚpartsÚis_absoluteÚanyÚ
ValueErrorrb   )rL   r—   rˆ   ÚposixÚpurer¡   s         r   Ú_safe_rel_install_pathr§     s§   € à
×
Ò
˜4Ñ
 Ô
 €CØ�LŠL‰NŒN€EÝ˜ÑÔ€DØBÐB˜dœjÐBÑBÔB€EØ×ÒÑÔð A ð A­#Ð-MÐ-MÀuÐ-MÑ-MÔ-MÑ*MÔ*Mð AÝÐ?¸Ð?Ð?Ñ@Ô@Ð@Ø�8Š8�E‰?Œ?Ðr   c                 óð   — g }t          |                      d¦  «        ¦  «        D ]P}|                     ¦   «         r:|                     |                     | ¦  «                             ¦   «         ¦  «         ŒQ|S )z8List files inside a skill directory in lock-file format.rŒ   )rc   r+   r�   r„   rƒ   r    )r2   Úfilesr•   s      r   Ú_skill_file_listrª     so   € à€EÝ˜	Ÿš¨Ñ,Ô,Ñ-Ô-ð Bð BˆØ�=Š=‰?Œ?ð 	BØ�LŠL˜×*Ò*¨9Ñ5Ô5×>Ò>Ñ@Ô@ÑAÔAÐAøØ€Lr   c                 ód   — 	 ddl m}  || ¦  «        S # t          $ r t          | ¦  «        cY S w xY w)zJReturn the same hash style the skills hub lock uses, falling back locally.r   )Úcontent_hash)Útools.skills_guardr¬   rI   r–   )rŠ   r¬   s     r   Ú_content_hashr®      sZ   € ð$Ø3Ð3Ð3Ð3Ð3Ð3àˆ|˜IÑ&Ô&Ð&øÝð $ð $ð $õ ˜Ñ#Ô#Ð#Ð#Ð#ð$øøøs   ‚ “/®/c                  ó„  — t          ¦   «         } i }|                      ¦   «         s|S t          |                      d¦  «        ¦  «        D ]v}t	          |                     | ¦  «        | ¬¦  «        rŒ'|j        }	 t          || ¦  «        }n# t          $ r Y ŒLw xY w|j	        }t          ||¦  «        }|||f}|||<   |||<   Œw|S )a%  Return official optional skills keyed by folder name and frontmatter name.

    Values are ``(folder_name, install_path, source_dir)``. Multiple keys may
    point to the same skill so callers can accept either the folder slug used
    by the hub lock or the user-facing frontmatter name.
    r&   r�   )r"   r9   rc   r+   r   rƒ   r   r§   r¤   r-   r.   )Úoptional_dirÚindexr1   ÚsrcÚinstall_pathÚfolder_namer3   r~   s           r   Ú_optional_skill_indexrµ   ,  sþ   € õ %Ñ&Ô&€LØ.0€EØ×ÒÑ Ô ð ØˆÝ˜<×-Ò-¨jÑ9Ô9Ñ:Ô:ð (ð (ˆÝ!Ø× Ò  Ñ.Ô.°\ð
ñ 
ô 
ð 	ð ØŒoˆð	Ý1°#°|ÑDÔDˆLˆLøÝð 	ð 	ð 	ØˆHð	øøøà”hˆÝ+¨H°kÑBÔBÐØ˜l¨CÐ0ˆØ"ˆˆkÑØ"'ˆÐÑÐØ€Ls   Á8B	Â	
BÂBÚbackup_rootc                 ó6  — |                       t          ¦  «        }||z  }|j                             dd¬¦  «         |                     ¦   «         rˆd}|                     |j        › d|› �¦  «                             ¦   «         r6|dz  }|                     |j        › d|› �¦  «                             ¦   «         °6|                     |j        › d|› �¦  «        }t          j        t          | ¦  «        t          |¦  «        ¦  «         | 
                    ¦   «         S )zLMove an existing skill directory into a restore backup, preserving rel path.TrQ   ry   Ú-)rƒ   rJ   r   ra   r9   Ú	with_namer-   ÚshutilÚmoverf   r    )rL   r¶   rˆ   Útargetr\   s        r   Ú_move_to_restore_backupr½   I  s  € à
×
Ò
�:Ñ
&Ô
&€CØ˜3Ñ€FØ
„M×Ò ¨tÐÑ4Ô4Ð4Ø‡}‚}�„ð =ØˆØ×Ò &¤+Ð8Ð8°Ð8Ð8Ñ9Ô9×@Ò@ÑBÔBð 	Ø�a‰KˆFð ×Ò &¤+Ð8Ð8°Ð8Ð8Ñ9Ô9×@Ò@ÑBÔBð 	à×!Ò! V¤[Ð";Ð";°6Ð";Ð";Ñ<Ô<ˆÝ
„K•�D‘	”	�3˜v™;œ;Ñ'Ô'Ð'Ø�<Š<‰>Œ>Ðr   F)Úrestorer-   r¾   c                óþ  — t          ¦   «         }|sddg g g dœS | dv r1t          t          |                     ¦   «         ¦  «        d„ ¬¦  «        ng }|s%|                     | ¦  «        }|€dd| › �g g g dœS |g}g }g }t          j        t          j        ¦  «         	                    d	¦  «        }t          d
z  d|› �z  }|D �]\  }	}
}t          t          |
                     d¦  «        Ž z  }t          |¦  «        }|                     ¦   «         ot          |¦  «        |k    }t          |dz  |	¦  «        }g }t                               ¦   «         r¯t          t                               d¦  «        ¦  «        D ]‡}t#          |¦  «        rŒ|j        }	 |                     t          ¦  «         n# t(          $ r Y ŒAw xY wt          ||j        ¦  «        }||k    rŒa|j        |	k    s||	|hv r|                     |¦  «         Œˆ|rÑ|D ]9}|                     ¦   «         r#|                     t/          ||¦  «        ¦  «         Œ:|                     ¦   «         r%|s#|                     t/          ||¦  «        ¦  «         |                     ¦   «         sF|j                             dd¬¦  «         t3          j        ||¦  «         |                     |	¦  «         �Œ|s�Œ�Œt7          d¬¦  «        }dd||||rt9          |¦  «        nddœS )a3  Restore one or all official optional skills from repo source.

    ``restore=False`` only performs exact-match provenance backfill. ``restore=True``
    repairs already-mutated/reorganized skills by backing up matching active
    copies and copying the official optional source into its canonical path.
    Fz,No official optional skills directory found.)ÚokÚmessageÚrestoredÚ
backfilledÚ	backed_up>   rŒ   Úallc                 ó   — | d         S )Nry   r   )Úitems    r   ú<lambda>z1restore_official_optional_skill.<locals>.<lambda>b  s
   € ¸4À¼7€ r   ©ÚkeyNz#Official optional skill not found: z%Y%m%d-%H%M%Sz.restore-backupszofficial-optional-rŸ   r&   TrQ   ©Úquietz(Official optional skill repair complete.r'   )rÀ   rÁ   rÂ   rÃ   rÄ   Ú
backup_dir)rµ   rc   r*   ÚvaluesÚgetr   Únowr   ÚutcÚstrftimerJ   r   rz   r–   r9   r.   r+   r   r   rƒ   r¤   r-   r„   r½   ra   rº   ÚcopytreeÚ_backfill_optional_provenancerf   )r-   r¾   r±   Útargetsr¼   rÂ   rÄ   Ú	timestampr¶   r´   r³   r²   ÚdestÚsrc_hashÚcanonical_okÚsrc_frontmatterÚmatchesr1   Ú	candidateÚcandidate_nameÚmatchrÃ   s                         r   Úrestore_official_optional_skillrß   W  s�  € õ "Ñ#Ô#€EØð KØÐ(VÐdfÐvxð  HJð  Kð  Kð  	KàGKÈ|ÐG[ÐG[�f•S˜Ÿš™œÑ(Ô(Ð.BÐ.BÐCÑCÔCÐCÐac€GØð Ø—’˜4‘”ˆØˆ>ØÐ,XÐRVÐ,XÐ,XÐfhÐxzð  JLð  Mð  Mð  MØ�(ˆà€HØ€IÝ”�Xœ\Ñ*Ô*×3Ò3°OÑDÔD€IÝÐ1Ñ1Ð4TÈÐ4TÐ4TÑT€Kà*1ð #ñ #Ñ&ˆ�\ 3Ý�D ,×"4Ò"4°SÑ"9Ô"9Ð:Ñ:ˆÝ˜S‘>”>ˆØ—{’{‘}”}ÐD­°4©¬¸HÒ)Dˆõ +¨3°Ñ+;¸[ÑIÔIˆØ ˆÝ×ÒÑÔð 	.Ý"¥:×#3Ò#3°JÑ#?Ô#?Ñ@Ô@ð .ð .�Ý)¨(Ñ3Ô3ð ØØ$œO�	ðØ×)Ò)­*Ñ5Ô5Ð5Ð5øÝ!ð ð ð Ø�Hðøøøå!1°(¸I¼NÑ!KÔ!K�Ø Ò$Ð$ØØ”> [Ò0Ð0°NÀ{ÐTcÐFdÐ4dÐ4dØ—N’N 9Ñ-Ô-Ð-øàð 	Ø ð Rð R�Ø—<’<‘>”>ð RØ×$Ò$Õ%<¸UÀKÑ%PÔ%PÑQÔQÐQøØ�{Š{‰}Œ}ð M \ð MØ× Ò Õ!8¸¸{Ñ!KÔ!KÑLÔLÐLØ—;’;‘=”=ð -Ø”×!Ò!¨$¸Ð!Ñ>Ô>Ð>Ý”  TÑ*Ô*Ð*Ø—’ Ñ,Ô,Ð,ùØð 	Ùñ	õ /°TÐ:Ñ:Ô:€JàØ=ØØ ØØ*3Ð;•c˜+Ñ&Ô&Ð&¸ðð ð s   ÆF)Æ)
F6Æ5F6c                  ó²  — i } t                                ¦   «         s| S t                                d¦  «        D ]ž}t          |¦  «        rŒ|j        }	 |                     ¦   «                              t                                ¦   «         ¦  «         n# t          t          f$ r Y Œlw xY w|  	                    |j
        g ¦  «                             |¦  «         ŒŸ| S )zCIndex installed skills by directory name with one active-tree scan.r&   )rJ   r9   r+   r   r   Úresolverƒ   r>   r¤   Ú
setdefaultr-   r„   )r±   r1   rÜ   s      r   Ú#_index_installed_skill_dirs_by_namerã   ž  sÞ   € à#%€EÝ×ÒÑÔð ØˆÝ×$Ò$ ZÑ0Ô0ð 	?ð 	?ˆÝ! (Ñ+Ô+ð 	ØØ”Oˆ	ð	Ø×ÒÑÔ×+Ò+­J×,>Ò,>Ñ,@Ô,@ÑAÔAÐAÐAøÝ�Ð$ð 	ð 	ð 	ØˆHð	øøøà×Ò˜œ¨Ñ,Ô,×3Ò3°IÑ>Ô>Ð>Ð>Ø€Ls   Á>BÂB%Â$B%Úskill_dir_nameÚinstalled_indexc                 óÂ   — | rt                                ¦   «         sdS |€t          ¦   «         }|                     | g ¦  «        }t	          |¦  «        dk    rdS |d         S )u  Locate an installed skill directory by its directory name.

    Used only as a fallback when the repo-derived install path doesn't exist in
    the active tree (upstream recategorized the skill after it was installed).
    Returns None when there is no match, or when the name is AMBIGUOUS â€” two
    skills sharing a directory name give us no basis to pick one, and guessing
    would write provenance onto the wrong skill. The caller still verifies a
    byte-identical content hash before recording anything.
    Nry   r   )rJ   r9   rã   rÏ   Úlen)rä   rå   rÛ   s      r   Ú!_find_installed_skill_dir_by_namerè   °  sj   € ð ð ¥×!2Ò!2Ñ!4Ô!4ð ØˆtØÐÝ=Ñ?Ô?ˆØ×!Ò! .°"Ñ5Ô5€GÝ
ˆ7�|„|�qÒÐØˆtØ�1Œ:Ðr   rÌ   c                 ó6  — t          ¦   «         }|                     ¦   «         sg S t          dz  dz  }	 |                     ¦   «         r(t          j        |                     d¬¦  «        ¦  «        ndi dœ}n!# t          j        t          f$ r di dœ}Y nw xY w|                     di ¦  «        }d„ | 	                    ¦   «         D ¦   «         }g }d	}d
}t          |                     d¦  «        ¦  «        D �]ö}	t          |	¦  «        rŒ|	j        }
	 t          |
|¦  «        }n3# t          $ r&}t                                d|
|¦  «         Y d
}~ŒWd
}~ww xY w|
j        }||v s||v rŒot          t'          |                     d¦  «        Ž z  }|                     ¦   «         r|                     ¦   «         ss|€t-          ¦   «         }t/          |
j        |¦  «        }|€Œã	 t          |t          ¦  «        }n4# t          $ r'}t                                d||¦  «         Y d
}~�Œ&d
}~ww xY w||v r�Œ4t1          |¦  «        t1          |
¦  «        k    r�ŒVt3          j        t6          j        ¦  «                             ¦   «         }dd|› �ddt=          |¦  «        |t?          |¦  «        ddi||dœ
||<   |                      |¦  «         | !                    |¦  «         d}| stE          d|› d�¦  «         �Œø|�r,|j         #                    dd¬¦  «         dd
l$}t          j%        |dd	¬¦  «        dz   }| &                    tO          |j        ¦  «        dd¬ ¦  «        \  }}	 tQ          j)        |d!d¬¦  «        5 }| *                    |¦  «         | +                    ¦   «          tQ          j,        | -                    ¦   «         ¦  «         d
d
d
¦  «         n# 1 swxY w Y   t]          ||¦  «         n5# t^          $ r( 	 tQ          j0        |¦  «         n# t          $ r Y nw xY w‚ w xY w|S )"a«  Mark already-present official optional skills as hub-installed.

    This covers the migration case where a skill used to be bundled (or was
    manually copied into the active skills tree) and later lives under
    optional-skills/. If the active copy is byte-identical to the official
    optional source, record official hub provenance without copying or
    reinstalling anything. Modified/local skills are left alone.
    ú.hubú	lock.jsonr   r6   ry   )ÚversionÚ	installedrí   c                 ób   — h | ],}t          |t          ¦  «        ¯|                     d ¦  «        ’Œ-S )r³   )Ú
isinstanceÚdictrÏ   )rV   Úentrys     r   ú	<setcomp>z0_backfill_optional_provenance.<locals>.<setcomp>Ú  sD   € ð ð ð àÝ�e�TÑ"Ô"ðØ�	Š	�.Ñ!Ô!ðð ð r   FNr&   z/Skipping optional skill with unsafe path %s: %srŸ   z(Skipping relocated optional skill %s: %sÚofficialz	official/ÚbuiltinrÃ   Úbackfilled_fromr!   )
ÚsourceÚ
identifierÚtrust_levelÚscan_verdictr¬   r³   r©   ÚmetadataÚinstalled_atÚ
updated_atTz  = z* (official optional provenance backfilled)rQ   r   é   )ÚindentÚensure_asciirT   z.lock_rX   rY   r]   )1r"   r9   rJ   ÚjsonÚloadsr:   ÚJSONDecodeErrorr>   râ   rÎ   rc   r+   r   r   r§   r¤   ro   rp   r-   r   rz   Úis_dirrã   rè   r–   r   rÐ   r   rÑ   Ú	isoformatr®   rª   r,   r„   Úprintra   r`   Údumpsre   rf   rg   rh   ri   rj   rk   rl   r   rm   rn   )rÌ   r°   Ú	lock_pathrq   rí   Úexisting_pathsrÃ   ÚchangedÚinstalled_dir_indexr1   r²   r³   ru   Ú	lock_namer×   rÖ   r`   Úpayloadrr   rs   rt   s                        r   rÔ   rÔ   Ç  s÷  € õ %Ñ&Ô&€LØ×ÒÑ Ô ð Øˆ	å˜VÑ# kÑ1€Ið/ØDM×DTÒDTÑDVÔDVÐ{�tŒz˜)×-Ò-°wÐ-Ñ?Ô?Ñ@Ô@Ð@ÐhiÐxzÐ\{Ð\{ˆˆøÝÔ ¥'Ð*ð /ð /ð /Ø¨2Ð.Ð.ˆˆˆð/øøøà—’ ¨RÑ0Ô0€Iðð à×%Ò%Ñ'Ô'ðñ ô €Nð €JØ€GØ;?ÐÝ˜<×-Ò-¨jÑ9Ô9Ñ:Ô:ð 6Pñ 6PˆÝ! (Ñ+Ô+ð 	ØØŒoˆð	Ý1°#°|ÑDÔDˆLˆLøÝð 	ð 	ð 	Ý�LŠLÐJÈCÐQRÑSÔSÐSØˆHˆHˆHˆHøøøøð	øøøð ”Hˆ	Ø˜	Ð!Ð! \°^Ð%CÐ%CØÝ�D ,×"4Ò"4°SÑ"9Ô"9Ð:Ñ:ˆØ�{Š{‰}Œ}ð 	 D§K¢K¡M¤Mð 	ð #Ð*Ý&IÑ&KÔ&KÐ#Ý4°S´XÐ?RÑSÔSˆDØˆ|ØðÝ5°d½JÑGÔG��øÝð ð ð Ý—’ÐGÈÈqÑQÔQÐQØ���‘øøøøðøøøð ˜>Ð)Ð)ÙÝ�T‰?Œ?�i¨™nœnÒ,Ð,Ùå”L¥¤Ñ.Ô.×8Ò8Ñ:Ô:ˆ	à Ø4 lÐ4Ð4Ø$Ø(Ý)¨$Ñ/Ô/Ø(Ý% dÑ+Ô+Ø*Ð,=Ð>Ø%Ø#ð 
ð  
ˆ	�)Ñð 	×Ò˜<Ñ(Ô(Ð(Ø×Ò˜)Ñ$Ô$Ð$ØˆØð 	PÝÐN˜ÐNÐNÐNÑOÔOÐOùàñ ØÔ×Ò t°dÐÑ;Ô;Ð;ð 	ˆˆˆå”*˜T¨!¸%Ð@Ñ@Ô@À4ÑGˆØ×'Ò'Ý�IÔ$Ñ%Ô%ØØð (ñ 
ô 
‰ˆˆHð
	Ý”˜2˜s¨WÐ5Ñ5Ô5ð %¸Ø—’˜Ñ Ô Ð Ø—’‘	”	�	Ý”˜Ÿš™œÑ$Ô$Ð$ð%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %õ ˜8 YÑ/Ô/Ð/Ð/øÝð 	ð 	ð 	ðÝ”	˜(Ñ#Ô#Ð#Ð#øÝð ð ð Ø�ðøøøàð	øøøð Ðs—   ³AA5 Á5BÂBÄDÄ
EÄ(E	Å	EÇG,Ç,
HÇ6HÈHÍO$ Í,AOÎ<O$ ÏOÏO$ ÏOÏO$ Ï$
PÏ/PÐPÐ
PÐPÐPÐPc                  óB  — t           dz  dz  } |                      ¦   «         st          ¦   «         S 	 t          j        |                      d¬¦  «        ¦  «        }n*# t          j        t          f$ r t          ¦   «         cY S w xY wt          ¦   «         }|                     d¦  «        pi  	                    ¦   «         D ]c}t          |t          ¦  «        rL|                     d¦  «        }|r5|                     t          |¦  «                             d¦  «        ¦  «         Œd|S )aq  Return install paths recorded in the skills-hub lock, as POSIX strings.

    Hub-installed skills are owned by the hub (``hermes skills uninstall``),
    never by bundled sync. Rename recovery must not move them even when their
    content happens to match a bundled origin hash, or the lock's
    ``install_path`` would point at a directory that no longer exists.
    rê   rë   r   r6   rí   r³   rŸ   )rJ   r9   r*   r   r  r:   r  r>   rÏ   rÎ   rï   rð   r,   rf   r<   )r  rq   Úpathsrñ   r³   s        r   Ú_read_hub_install_pathsr  7  s  € õ ˜VÑ# kÑ1€IØ×ÒÑÔð Ý‰uŒuˆðÝŒz˜)×-Ò-°wÐ-Ñ?Ô?Ñ@Ô@ˆˆøÝÔ ¥'Ð*ð ð ð Ý‰uŒuˆˆˆðøøøå‘e”e€EØ—(’(˜;Ñ'Ô'Ð-¨2×5Ò5Ñ7Ô7ð 8ð 8ˆÝ�e�TÑ"Ô"ð 	8Ø Ÿ9š9 ^Ñ4Ô4ˆLØð 8Ø—	’	�#˜lÑ+Ô+×1Ò1°#Ñ6Ô6Ñ7Ô7Ð7øØ€Ls   ±(A Á$BÂ Bc                  ó$  — i } t                                ¦   «         s| S t                                d¦  «        D ]W}t          |¦  «        rŒ|j        }t          ||j        ¦  «        }|                      |g ¦  «                             |¦  «         ŒX| S )zÖIndex every skill in the user's tree by frontmatter name.

    Returns ``{skill_name: [skill_dir, ...]}``. Used by rename recovery to
    locate a bundled skill that upstream moved to a new category/directory.
    r&   )	rJ   r9   r+   r   r   r.   r-   râ   r„   )r±   r1   r2   r-   s       r   Ú_index_active_skillsr  O  s–   € ð $&€EÝ×ÒÑÔð ØˆÝ×$Ò$ ZÑ0Ô0ð 5ð 5ˆÝ! (Ñ+Ô+ð 	ØØ”Oˆ	Ý ¨)¬.Ñ9Ô9ˆØ×Ò˜˜rÑ"Ô"×)Ò)¨)Ñ4Ô4Ð4Ð4Ø€Lr   r…   Úorigin_hashr×   Úactive_indexÚ	hub_pathsc                 ó†  — |sdS |                      | g ¦  «        D �]¤}||k    s|                     ¦   «         sŒ	 |                     t          ¦  «                             ¦   «         }n# t
          $ r Y ŒXw xY w||v rŒat          |¦  «        |k    rI|sFt          d| › d|                     t          ¦  «                             ¦   «         › d|› d| › d�	¦  «         Œ½	 |j         	                    dd¬¦  «         t          j        t          |¦  «        t          |¦  «        ¦  «         n7# t          t          f$ r# t                               d	||d¬
¦  «         Y  dS w xY wt                               d||¦  «         |sCt          d| › d|› d|                     t          ¦  «                             ¦   «         › d�¦  «         |c S dS )uI  Move a bundled skill's stale copy to its new canonical path.

    When upstream RENAMES or RECATEGORIZES a bundled skill, the manifest key
    (frontmatter name) still matches but ``dest`` is a brand-new path that does
    not exist yet. Without recovery, ``sync_skills()`` falls through to its
    "in manifest but not on disk" branch and misreads the skill as
    *user-deleted*: the old directory is stranded forever and never receives
    another update.

    A stale copy is only moved when it is byte-identical to ``origin_hash`` â€”
    the hash recorded the last time sync wrote that skill â€” which proves the
    directory is the copy *we* placed there rather than the user's own work.
    Anything else (user-edited, hub-installed) is left untouched.

    Returns the relative source path when a move happened, else ``None``.
    Nõ     âš  z: upstream moved this skill to z, but your modified copy at uD    was kept â€” it will not receive updates. Run `hermes skills reset z( --restore` to move to the new location.TrQ   z)Could not relocate renamed skill %s -> %sr^   z)Relocated renamed bundled skill: %s -> %su     â†’ z (moved u    â†’ ú))rÏ   r  rƒ   rJ   r    r¤   r–   r  r   ra   rº   r»   rf   r>   r?   ro   ÚwarningÚinfo)r…   r  r×   r  r  rÌ   rÜ   rˆ   s           r   Ú_recover_renamed_skillr  a  s8  € ð0 ð Øˆtà!×%Ò% j°"Ñ5Ô5ð #ñ #ˆ	Ø˜ÒÐ I×$4Ò$4Ñ$6Ô$6ÐØð	Ø×'Ò'­
Ñ3Ô3×<Ò<Ñ>Ô>ˆCˆCøÝð 	ð 	ð 	ØˆHð	øøøð �)ÐÐØÝ�YÑÔ ;Ò.Ð.ð ð Ýð4˜Zð 4ð 4Ø×'Ò'­
Ñ3Ô3×<Ò<Ñ>Ô>ð4ð 4à(+ð4ð 4ð :Dð4ð 4ð 4ñô ð ð ð	ØŒK×Ò d°TÐÑ:Ô:Ð:ÝŒK�˜I™œ­¨D©	¬	Ñ2Ô2Ð2Ð2øÝ�Ð!ð 	ð 	ð 	Ý�NŠNØ;¸YÈØð ñ ô ð ð �4�4�4ð	øøøõ 	�ŠÐ?ÀÈDÑQÔQÐQØð 	eÝÐc˜:ÐcÐc¨sÐcÐc¸×9IÒ9IÍ*Ñ9UÔ9U×9^Ò9^Ñ9`Ô9`ÐcÐcÐcÑdÔdÐdØˆ
ˆ
ˆ
Øˆ4s$   º,A'Á'
A4Á3A4ÃAD%Ä%/EÅEc                 óŒ  — t           t          z                       ¦   «         r| st          d¦  «         g g dg g dg ddœS t	          ¦   «         }|                     ¦   «         sg g dg g g dg dœS t
                               dd¬¦  «         t          ¦   «         }t          |¦  «        }d„ |D ¦   «         }t          ¦   «         }t          ¦   «         }g }d}d}	g }
g }g }g }g }d}|D �]º\  }}||v r|                     |¦  «         Œ t          ||¦  «        }t          |¦  «        }|                     d	¦  «        }|                     ¦   «         r°|                     ¦   «         sœ	 |j                             dd¬¦  «         t!          j        t%          |¦  «        t%          |¦  «        ¦  «         t&                               d
|¦  «         n4# t*          t,          f$ r  t&                               d|d¬¦  «         Y nw xY w|                     ¦   «         so||v rk|€t1          ¦   «         }t3          ¦   «         }	t5          ||                     |d¦  «        |||	pt9          ¦   «         | ¦  «        }|r|                     |¦  «         ||v r‘|                     |¦  «         |dz  }| st          d|› d�¦  «         |                     ¦   «         rLt          |¦  «        |k    r9t;          |¦  «         | st          d|› �¦  «         |                     |d¦  «         �Œ0||vrã	 |                     ¦   «         r7|dz  }t          |¦  «        |k    r|||<   nx| st          d|› d|› d�¦  «         n_|j                             dd¬¦  «         t!          j        ||¦  «         |
                     |¦  «         |||<   | st          d|› �¦  «         �Œá# t*          t,          f$ r"}| st          d|› d|› �¦  «         Y d}~�Œd}~ww xY w|                     ¦   «         �r‰|                     |d¦  «        }|r||k    r|dz  }�ŒQt          |¦  «        }|s|||<   ||k    r|dz  }n|dz  }�ŒztA          ||¦  «        r,|                     |¦  «         | st          d|› d�¦  «         �Œ¶||k    �rñ	 |                     d	¦  «        }|                     ¦   «         rt;          |¦  «         t!          j        t%          |¦  «        t%          |¦  «        ¦  «         	 t!          j        ||¦  «         |||<   |                     |¦  «         | st          d|› d�¦  «         	 t;          |¦  «         n4# t*          t,          f$ r  t&           !                    d|d¬¦  «         Y nw xY wnÆ# t*          t,          f$ r² |                     ¦   «         rœ|                     ¦   «         rE	 t;          |¦  «         n4# t*          t,          f$ r  t&                               d|d¬¦  «         Y nw xY w|                     ¦   «         s/t!          j        t%          |¦  «        t%          |¦  «        ¦  «         ‚ w xY w�Œx# t*          t,          f$ r"}| st          d|› d|› �¦  «         Y d}~�Œ¦d}~ww xY w|dz  }�Œµ|dz  }�Œ¼tE          t9          | #                    ¦   «         ¦  «        |z
  ¦  «        }|D ]}||= Œ| $                    d¦  «        D ]¢}| %                    |¦  «        }t
          |z  }|                     ¦   «         sm	 |j                             dd¬¦  «         t!          j&        ||¦  «         Œh# t*          t,          f$ r&}t&           !                    d ||¦  «         Y d}~Œšd}~ww xY wŒ£tO          |¦  «         tQ          | ¬!¦  «        }|
||||||tS          |¦  «        ||d"œ
S )#zî
    Sync bundled skills into ~/.hermes/skills/ using the manifest.

    Returns:
        dict with keys: copied (list), updated (list), skipped (int),
                        user_modified (list), cleaned (list), total_bundled (int)
    uJ     (skipped â€” profile opted out of bundled skills via .no-bundled-skills)r   T)ÚcopiedÚupdatedÚskippedÚuser_modifiedÚcleanedÚtotal_bundledÚoptional_provenance_backfilledÚskipped_opt_out)r  r  r  r  r   Ú
suppressedr!  r"  rQ   c                 ó   — h | ]\  }}|’ŒS r   r   )rV   r-   rB   s      r   rò   zsync_skills.<locals>.<setcomp>Ä  s   € Ð8Ð8Ð8™g˜d A�TÐ8Ð8Ð8r   Nz.bakz#Recovered orphaned skill backup: %sz*Could not recover orphaned skill backup %sr^   r'   ry   u     â‡¢ z7 (deferred to external_dirs, not written to local tree)u     âœ“ removed stale shadow of r  uw   : bundled version shipped but you already have a local skill by this name â€” yours was kept. Run `hermes skills reset z)` to replace it with the bundled version.z  + z  ! Failed to copy ú: z  ~ z (user-modified, skipping)u     â†‘ z
 (updated)zCould not remove backup %sz.Could not clear partial copy %s during restorez  ! Failed to update zDESCRIPTION.mdzCould not copy %s: %srË   )
r  r  r  r  r   r$  Ú	relocatedr!  r"  Úshadowed_by_external)*ÚHERMES_HOMEÚNO_BUNDLED_SKILLS_MARKERr9   r  r   rJ   ra   rD   r†   rN   r4   r„   r‰   r–   Úwith_suffixr   rº   r»   rf   ro   r  r>   r?   r  r  r  r  rÏ   r*   Ú_rmtree_writableÚpoprÓ   Ú_is_tracked_user_modificationrp   rc   Úkeysr+   rƒ   Úcopy2rv   rÔ   rç   ) rÌ   r   ÚmanifestÚbundled_skillsÚbundled_namesr$  Úexternal_indexr(  r  r  r  r  r  Úsuppressed_skippedr'  r  r…   Ú	skill_srcr×   Úbundled_hashÚ_orphanÚ_moved_fromru   r  Ú	user_hashÚbackupr   r-   Údesc_mdrˆ   Ú	dest_descr"  s                                    r   Úsync_skillsr>  £  sŸ	  € õ 	Õ.Ñ.×6Ò6Ñ8Ô8ð 
Øð 	`ÝÐ^Ñ_Ô_Ð_à R°AØ¨BÀØ.0ÀTð
ð 
ð 	
õ #Ñ$Ô$€KØ×ÒÑÔð 
à R°AØ¨B¸bÐSTØ.0ð
ð 
ð 	
õ ×Ò˜T¨DÐÑ1Ô1Ð1ÝÑÔ€HÝ-¨kÑ:Ô:€NØ8Ð8¨Ð8Ñ8Ô8€MÝ'Ñ)Ô)€Jå0Ñ2Ô2€NØ&(Ðð 59€LØ$(€Ià€FØ€GØ€MØ$&ÐØ€IØ€Gà!/ð ñ Ñˆ
�Ið ˜Ð#Ð#Ø×%Ò% jÑ1Ô1Ð1Øå% i°Ñ=Ô=ˆÝ  Ñ+Ô+ˆð ×"Ò" 6Ñ*Ô*ˆØ�>Š>ÑÔð 		 D§K¢K¡M¤Mð 		ðØ”×!Ò!¨$¸Ð!Ñ>Ô>Ð>Ý”�C ™LœL­#¨d©)¬)Ñ4Ô4Ð4Ý—’ÐAÀ7ÑKÔKÐKÐKøÝ�WÐ%ð ð ð Ý—’Ø@À'Ø!ð ñ ô ð ð ð ðøøøð �{Š{‰}Œ}ð 	- ¨xÐ!7Ð!7ØÐ#Ý3Ñ5Ô5�Ý3Ñ5Ô5�	Ý0ØØ—’˜Z¨Ñ,Ô,ØØØÐ"�S™UœUØñô ˆKð ð -Ø× Ò  Ñ,Ô,Ð,à˜Ð'Ð'ð
 !×'Ò'¨
Ñ3Ô3Ð3Ø�q‰LˆGØð Ýð1˜Zð 1ð 1ð 1ñô ð ð �{Š{‰}Œ}ð /¥¨4¡¤°LÒ!@Ð!@Ý  Ñ&Ô&Ð&Øð IÝÐG¸:ÐGÐGÑHÔHÐHØ—’˜Z¨Ñ.Ô.Ð.Ùà˜XÐ%Ð%ðCØ—;’;‘=”=ð 3ð ˜q‘L�GÝ  ‘”¨,Ò6Ð6Ø/;˜ Ñ,Ð,Ø"ð ÝðG Zð Gð GàBLðGð Gð Gñô ð øð ”K×%Ò%¨d¸TÐ%ÑBÔBÐBÝ”O I¨tÑ4Ô4Ð4Ø—M’M *Ñ-Ô-Ð-Ø+7�H˜ZÑ(Ø ð 3ÝÐ1 ZÐ1Ð1Ñ2Ô2Ð2ùøÝ�WÐ%ð Cð Cð CØð CÝÐA°
ÐAÐA¸aÐAÐAÑBÔBÐBøøøøùøøøøðCøøøð
 �[Š[‰]Œ]ñ P	à"Ÿ,š, z°2Ñ6Ô6ˆKð ð ˜|¨{Ò:Ð:Ø˜1‘�Ùå! $™œˆIàð 	ð (1�˜Ñ$Ø Ò,Ð,Ø˜q‘L�G�Gð ˜q‘L�GÙå,¨[¸)ÑDÔDð à×$Ò$ ZÑ0Ô0Ð0Øð IÝÐG ÐGÐGÐGÑHÔHÐHÙð ˜{Ò*Ñ*ð'Ià!×-Ò-¨fÑ5Ô5�Fð
 —}’}‘”ð 1Ý(¨Ñ0Ô0Ð0Ý”K¥ D¡	¤	­3¨v©;¬;Ñ7Ô7Ð7ðÝœ¨	°4Ñ8Ô8Ð8Ø/;˜ Ñ,ØŸš zÑ2Ô2Ð2Ø$ð CÝ!Ð"A¨:Ð"AÐ"AÐ"AÑBÔBÐBð^Ý,¨VÑ4Ô4Ð4Ð4øÝ '­Ð1ð ^ð ^ð ^Ý"ŸLšLÐ)EÀvÐX\˜LÑ]Ô]Ð]Ð]Ð]ð^øøøøøå#¥WÐ-ð ð ð ð "Ÿ=š=™?œ?ð 
DØ#Ÿ{š{™}œ}ð &ð!&Ý$4°TÑ$:Ô$:Ð$:Ð$:øÝ(/µÐ'9ð !&ð !&ð !&Ý$*§N¢NØ(XØ(,°tð %3ñ %&ô %&ð %&ð %&ð %&ð!&øøøð
 $(§;¢;¡=¤=ð DÝ &¤­C°©K¬K½¸T¹¼Ñ CÔ CÐ CØðøøøùøõ   ¥Ð)ð Ið Ið IØ ð IÝÐG°jÐGÐGÀAÐGÐGÑHÔHÐHøøøøùøøøøðIøøøð ˜1‘�‘ð �q‰LˆG‰Gõ •S˜Ÿš™œÑ)Ô)¨MÑ9Ñ:Ô:€GØð ð ˆØ�TˆNˆNð ×$Ò$Ð%5Ñ6Ô6ð Bð BˆØ×!Ò! +Ñ.Ô.ˆÝ Ñ$ˆ	Ø×ÒÑ!Ô!ð 	BðBØÔ ×&Ò&¨t¸dÐ&ÑCÔCÐCÝ”˜W iÑ0Ô0Ð0Ð0øÝ�WÐ%ð Bð Bð BÝ—’Ð4°g¸qÑAÔAÐAÐAÐAÐAÐAÐAøøøøðBøøøð		Bõ �HÑÔÐÝ%BÈÐ%OÑ%OÔ%OÐ"ð ØØØ&ØØ(ØÝ˜^Ñ,Ô,Ø*HØ 4ðð ð s¿   ÅA&GÇ.G5Ç4G5ÌB*OÏO4ÏO/Ï/O4ÒA'YÔAVÕUÕVÕ.VÖ	VÖVÖVÖYÖ9Y×
W×Y×.XØYØ
XØAYÙYÙZÙ)ZÚZÜ 1]Ý^	Ý#^Þ^	c                 óø   ‡— t          | ¦  «                             ¦   «         }t                               ¦   «         }||j        vrt	          d|›d|›d�¦  «        ‚ddlŠˆfd„}t          j        | |¬¦  «         dS )aª  Remove a directory tree, making read-only entries writable first.

    Handles immutable package sources (Nix store, deb/rpm installs) that
    preserve read-only permissions on copied files *and* directories
    (``r-xr-xr-x``).  Removing a child requires write permission on its
    parent directory, so the retry handler makes the failing path **and its
    parent** writable before re-attempting.  See #34860, #34972.
    zrefusing to rmtree z: not strictly under u    (scope guard â€” see #48200)r   Nc                 ó¼   •— t           j                             |¦  «        |fD ]-}	 t          j        |‰j        ¦  «         Œ# t
          $ r Y Œ*w xY w | |¦  «         d S ©N)rg   rL   ÚdirnameÚchmodÚS_IRWXUr>   )Úfuncr•   r_   r¼   Ústats       €r   Ú	_on_errorz#_rmtree_writable.<locals>._on_errorÛ  st   ø€ õ ”w—’ uÑ-Ô-¨uÐ5ð 	ð 	ˆFðÝ”˜ ¤Ñ.Ô.Ð.Ð.øÝð ð ð Ø�ðøøøàˆˆU‰Œˆˆˆs   ¦AÁ
AÁA)Úonerror)r   rá   rJ   rR   r¤   rF  rº   Úrmtree)rL   r¼   Úskills_rootrG  rF  s       @r   r,  r,  ·  s±   ø€ õ( �$‰ZŒZ×ÒÑ!Ô!€FÝ×$Ò$Ñ&Ô&€Kð ˜&œ.Ð(Ð(Ýð, &ð ,ð ,Àð ,ð ,ð ,ñ
ô 
ð 	
ð €K€K€Kðð ð ð ð õ „M�$ 	Ð*Ñ*Ô*Ð*Ð*Ð*r   c                 ó.  — t          ¦   «         }t          ¦   «         }t          |¦  «        }t          |¦  «        }| |v }| |v }|s|sddd| › d�ddœS d}|rv|sddd| › d�ddœS t	          ||          |¦  «        }	|	                     ¦   «         r?	 t          |	¦  «         d	}n,# t          t          f$ r}
dd
d|	› d|
› d�ddœcY d}
~
S d}
~
ww xY w|r|| = t          |¦  «         t          d	¬¦  «        }|r|r	d}d| › d�}n|r	d}d| › d�}nd}d| › d�}d	|||dœS )u;  
    Reset a bundled skill's manifest tracking so future syncs work normally.

    When a user edits a bundled skill, subsequent syncs mark it as
    ``user_modified`` and skip it forever â€” even if the user later copies
    the bundled version back into place, because the manifest still holds
    the *old* origin hash. This function breaks that loop.

    Args:
        name: The skill name (matches the manifest key / skill frontmatter name).
        restore: If True, also delete the user's copy in SKILLS_DIR and let
                 the next sync re-copy the current bundled version. If False
                 (default), only clear the manifest entry â€” the user's
                 current copy is preserved but future updates work again.

    Returns:
        dict with keys:
          - ok: bool, whether the reset succeeded
          - action: one of "manifest_cleared", "restored", "not_in_manifest",
                    "bundled_missing"
          - message: human-readable description
          - synced: dict from sync_skills() if a sync was triggered, else None
    FÚnot_in_manifestú'zi' is not a tracked bundled skill. Nothing to reset. (Hub-installed skills use `hermes skills uninstall`.)N)rÀ   ÚactionrÁ   ÚsyncedÚbundled_missingur   ' has no bundled source â€” manifest entry preserved but cannot restore from bundled (skill was removed upstream).TÚ	not_resetzCould not delete user copy at r&  u3   . Manifest entry preserved â€” nothing was changed.rË   rÂ   z
Restored 'z' from bundled source.z/' (no prior user copy, re-copied from bundled).Úmanifest_clearedzCleared manifest entry for 'zf'. Future `hermes update` runs will re-baseline against your current copy and accept upstream changes.)rD   r   r†   rð   r‰   r9   r,  r>   r?   rv   r>  )r-   r¾   r1  r   r2  Úbundled_by_nameÚin_manifestÚ
is_bundledÚdeleted_user_copyr×   ru   rO  rN  rÁ   s                 r   Úreset_bundled_skillrW  è  sG  € õ0 ÑÔ€HÝ"Ñ$Ô$€KÝ-¨kÑ:Ô:€NÝ˜>Ñ*Ô*€Oà˜(Ð"€KØ˜Ð(€Jàð 	
˜zð 	
àØ'ðI�Dð Ið Ið Ið ð
ð 
ð 	
ð ÐØð Øð 		àØ+ðU˜ð Uð Uð Uð ðð ð õ & o°dÔ&;¸[ÑIÔIˆØ�;Š;‰=Œ=ð 	ðÝ  Ñ&Ô&Ð&Ø$(Ð!Ð!øÝ�WÐ%ð 	ð 	ð 	àØ)ðM¸ð Mð MÀð Mð Mð Mð #ðð ð ð ð ð ð ð øøøøð	øøøð ð "Ø�TˆNÝ˜Ñ!Ô!Ð!õ ˜tÐ$Ñ$Ô$€Fàð 
Ð$ð 
ØˆØ;˜tÐ;Ð;Ð;ˆˆØ	ð 	
àˆØT˜tÐTÐTÐTˆˆà#ˆðW¨4ð Wð Wð Wð 	ð
  &°WÈÐOÐOÐOs   ÂB  Â C	Â1CÂ>C	ÃC	r:  c                 ó,   — t          | ¦  «        o|| k    S )a·  Whether an on-disk skill counts as a user modification ``hermes update`` keeps.

    Shared by the sync loop (which decides what to skip) and
    ``list_user_modified_bundled_skills`` (which surfaces the names) so the two
    can never drift. A skill is a tracked modification only when it has a
    recorded origin hash (an un-baselined / v1 entry with an empty hash is not)
    and its current content hash differs from that origin.
    )Úbool)r  r:  s     r   r.  r.  K  s   € õ �ÑÔÐ9 ¨kÒ!9Ð9r   c                  óŠ  — t          ¦   «         } | sg S t          ¦   «         }g }t          |¦  «        D ]y\  }}|                      |d¦  «        }|sŒt	          ||¦  «        }|                     ¦   «         sŒCt          |t          |¦  «        ¦  «        r|                     |||dœ¦  «         Œz| 	                    d„ ¬¦  «         |S )u¯  Return the bundled skills that ``hermes update`` keeps because the user
    edited them locally.

    A skill counts as user-modified when its on-disk copy no longer matches the
    origin hash recorded in the manifest the last time it was synced â€” the exact
    same test the sync loop uses to decide what to skip. This is the discovery
    half of that behavior, so a user can find the names the ``~ N user-modified
    (kept)`` notice only counts.

    Returns a list (sorted by name) of dicts:
        ``{"name": str, "dest": Path, "bundled_src": Path}``
    where ``dest`` is the user's copy and ``bundled_src`` is the current stock
    copy (so callers can diff or restore).
    r'   )r-   r×   Úbundled_srcc                 ó   — | d         S )Nr-   r   )ru   s    r   rÈ   z3list_user_modified_bundled_skills.<locals>.<lambda>x  s
   €   &¤	€ r   rÉ   )
rD   r   r†   rÏ   r‰   r9   r.  r–   r„   Úsort)r1  r   Úmodifiedr…   r2   r  r×   s          r   Ú!list_user_modified_bundled_skillsr_  W  så   € õ ÑÔ€HØð Øˆ	Ý"Ñ$Ô$€KØ€HÝ!9¸+Ñ!FÔ!Fð ð Ñˆ
�IØ—l’l :¨rÑ2Ô2ˆð ð 	ØÝ% i°Ñ=Ô=ˆØ�{Š{‰}Œ}ð 	ØÝ(¨µiÀ±o´oÑFÔFð 	Ø�OŠOØ#¨TÀ)ÐLÐLñô ð øð ‡M‚MÐ)Ð)€MÑ*Ô*Ð*Ø€Or   c                 ó¸   — 	 |                       ¦   «         }n# t          $ r Y dS w xY wd|v r|dfS 	 ||                     d¦  «        fS # t          $ r |dfcY S w xY w)zÿRead a file once for diffing.

    Returns ``(raw_bytes, text)`` where ``text`` is ``None`` if the file is
    binary; ``(None, None)`` if it could not be read. Returning the raw bytes
    lets the caller compare binary files without re-reading them.
    ©NNó    Nr   )r’   r>   ÚdecodeÚUnicodeDecodeError)rL   rq   s     r   Ú_read_for_diffre  |  s”   € ðØ�ŠÑ Ô ˆˆøÝð ð ð Øˆzˆzðøøøà�$€€Ø�TˆzÐðØ�T—[’[ Ñ)Ô)Ð)Ð)øÝð ð ð Ø�TˆzÐÐÐðøøøs   ‚ —
%¤%±A ÁAÁAc                 óH  — ddl }t          ¦   «         }t          t          |¦  «        ¦  «        }|                     | ¦  «        }|€d| ddg d| › d�dœS t          ||¦  «        }|                     ¦   «         sd| ddg d| › d	|› d
�dœS t          t          |¦  «        ¦  «        }t          t          |¦  «        ¦  «        }g }t          ||z  ¦  «        D �]}	|	|v }
|	|v }|
rt          ||	z  ¦  «        nd\  }}|rt          ||	z  ¦  «        nd\  }}|
r¡|rŸ|�|€ ||k    r|                     |	dddœ¦  «         Œe||k    rŒld                     |                     |                     d¬¦  «        |                     d¬¦  «        d|	› �d|	› �¬¦  «        ¦  «        }|                     |	d|dœ¦  «         Œà|
r|                     |	dd|	› �dœ¦  «         Œÿ|                     |	dd|	› �dœ¦  «         �Œt          |¦  «        }d| d|||sd| › d�nd| › dt!          |¦  «        › d�dœS )u8  Diff a user's copy of a bundled skill against the current stock version.

    Lets a user see exactly what diverged before deciding whether to keep their
    edits or ``hermes skills reset`` back to upstream.

    Returns a dict:
        ``ok`` (bool), ``name`` (str), ``found`` (bool â€” bundled source exists),
        ``modified`` (bool), ``message`` (str),
        ``diffs``: list of ``{"path": str, "status": str, "diff": str}`` where
        status is one of ``modified`` / ``added`` (only in user copy) /
        ``removed`` (only in bundled) / ``binary``.
    r   NFrM  zv' is not a tracked bundled skill (no stock version to diff against). Hub-installed skills use `hermes skills inspect`.)rÀ   r-   Úfoundr^  ÚdiffsrÁ   TzNo local copy of 'z' found at rš   ra  Úbinaryz<binary file differs>)rL   ÚstatusÚdiffr'   )Úkeependszstock/zyours/)ÚfromfileÚtofiler^  Úaddedz+ only in your copy: Úremovedz- only in stock: z' matches the stock version.z$' differs from the stock version in z	 file(s).)Údifflibr   rð   r†   rÏ   r‰   r9   r*   rª   rc   re  r„   rb   Úunified_diffr;   rY  rç   )r-   rq  r   rS  r[  r×   Ú
user_filesÚstock_filesrh  rˆ   Úin_userÚin_stockÚ
user_bytesÚ	user_textÚstock_bytesÚ
stock_textÚtextr^  s                     r   Údiff_bundled_skillr|  �  s4  € ð €N€N€Nå"Ñ$Ô$€KÝÕ3°KÑ@Ô@ÑAÔA€OØ!×%Ò% dÑ+Ô+€KØÐàØØØØðT�Dð Tð Tð Tð

ð 

ð 
	
õ " +¨{Ñ;Ô;€DØ�;Š;‰=Œ=ð 
àØØØØØD¨DÐDÐD¸TÐDÐDÐDð
ð 
ð 	
õ Õ% dÑ+Ô+Ñ,Ô,€JÝÕ& {Ñ3Ô3Ñ4Ô4€Kà€EÝ�j ;Ñ.Ñ/Ô/ð %ñ %ˆØ˜Ð#ˆØ˜+Ð%ˆà*1ÐC�N˜4 #™:Ñ&Ô&Ð&°|ñ 	ˆ
�Ið 2:ÐK�N˜;¨Ñ,Ñ-Ô-Ð-¸|ñ 	 ˆ�Zð ð 	�xð 	ØÐ  JÐ$6ð  Ò,Ð,Ø—L’LØ!$°ÐBYÐZÐZñô ð ð Ø˜JÒ&Ð&ØØ—7’7Ø×$Ò$Ø×)Ò)°4Ð)Ñ8Ô8Ø×(Ò(°$Ð(Ñ7Ô7Ø+ c˜^˜^Ø) C˜>˜>ð	 %ñ ô ñô ˆDð �LŠL #°ÀTÐJÐJÑKÔKÐKÐKØð 	Ø�LŠLØ¨Ð9VÐQTÐ9VÐ9VÐWÐWñô ð ð ð �LŠLØ¨	Ð;TÈsÐ;TÐ;TÐUÐUñô ð ñ õ �E‰{Œ{€HàØØØØð ðUÐ2�Ð2Ð2Ð2Ð2àT�TÐTÐT½sÀ5¹z¼zÐTÐTÐTðð ð r   Úenabledc                 ó�  — t           t          z  }|                     ¦   «         }	 | r=t                                dd¬¦  «         |                     dd¬¦  «         | }|rdnd}n|r|                     ¦   «          |}|rdnd	}n1# t          $ r$}d
d
t          |¦  «        d|› d|› �dœcY d}~S d}~ww xY wd|t          |¦  «        |dœS )aj  Toggle the .no-bundled-skills opt-out marker for the active profile.

    When ``enabled`` is True, writes HERMES_HOME/.no-bundled-skills so the
    installer, ``hermes update``, and any direct sync stop seeding bundled
    skills. When False, removes the marker so seeding resumes on the next
    sync. This is the on-disk-state half of ``hermes skills opt-out`` /
    ``opt-in``; removal of already-present skills is a separate, explicit
    step (see ``remove_pristine_bundled_skills``).

    Returns:
        dict with keys: ok (bool), changed (bool), marker (str path),
                        message (str).
    TrQ   z‹This profile opted out of bundled-skill seeding (`hermes skills opt-out`).
Delete this file to re-enable sync on the next `hermes update`.
r   r6   zpOpted out of bundled skills. Future install / update / sync runs will not seed bundled skills into this profile.u1   Already opted out â€” marker was already present.zgOpted back in. The next `hermes update` (or `hermes skills opt-in --sync`) will re-seed bundled skills.u&   Not opted out â€” no marker to remove.Fz#Could not update opt-out marker at r&  )rÀ   r	  ÚmarkerrÁ   N)r)  r*  r9   ra   Ú
write_textrn   r>   rf   )r}  r  Úexistedr	  rÁ   ru   s         r   Úset_bundled_skills_opt_outr‚  ò  sU  € õ Õ3Ñ3€FØ�mŠm‰oŒo€Gð
Øð 	Ý×Ò d°TÐÑ:Ô:Ð:Ø×ÒðTð !ð	 ñ ô ð ð "�kˆGð ðIð Gð Gð Ið	 ˆGð ð  Ø—’‘”�ØˆGð ð>ð ?ð ?ð >ð	 øøõ ð 
ð 
ð 
à EµS¸±[´[ØJ¸VÐJÐJÀqÐJÐJð
ð 
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøøð
øøøð
  7µc¸&±k´kÈgÐVÐVÐVs   ¥AB Â
B1ÂB,Â&B1Â,B1c                  óD   — t           t          z                       ¦   «         S )z=Return True if the active profile carries the opt-out marker.)r)  r*  r9   r   r   r   Úis_bundled_skills_opt_outr„  $  s   € åÕ2Ñ2×:Ò:Ñ<Ô<Ð<r   Údry_runc                 ól  — t          ¦   «         }t          ¦   «         }t          t          |¦  «        ¦  «        }g }g }t	          |                     ¦   «         ¦  «        D �]\  }}|                     |¦  «        }|€|                     |ddœ¦  «         Œ6t          ||¦  «        }	|	 	                    ¦   «         s
| s||v r||= Œdt          |	¦  «        }
|
|k    r|                     |ddœ¦  «         Œ’| r|                     |¦  «         Œª	 t          |	¦  «         n9# t          t          f$ r%}|                     |d|› �dœ¦  «         Y d}~Œìd}~ww xY w||v r||= |                     |¦  «         �Œ| s|rt          |¦  «         | rdnd}|› dt          |¦  «        › d	t          |¦  «        › d
�}d||| |dœS )aý  Delete bundled skills that are present, manifest-tracked, AND unmodified.

    Safety is the whole point of this function. A skill on disk is removed
    ONLY when all of these hold:
      - it is recorded in the sync manifest (so it is genuinely a bundled
        skill, not a hub-installed or hand-written one), AND
      - it still exists in the bundled source (so we can hash-compare), AND
      - its on-disk copy is byte-identical to the manifest origin hash
        (so the user has not edited it).

    Anything user-modified, hub-installed, or locally authored is left
    untouched and reported under ``skipped``. The manifest entry for each
    removed skill is dropped so a later opt-in re-seed treats it as new.

    Args:
        dry_run: When True, compute what would be removed without deleting.

    Returns:
        dict with keys: ok (bool), removed (list[str]),
                        skipped (list[dict]) where each dict is
                        {name, reason}, dry_run (bool), message (str).
    Nz$no bundled source (removed upstream))r-   Úreasonzuser-modified (kept)zdelete failed: zWould removeÚRemovedÚ z! pristine bundled skill(s); kept rš   T)rÀ   rp  r  r…  rÁ   )rD   r   rð   r†   rc   rd   rÏ   r„   r‰   r9   r–   r,  r>   r?   rv   rç   )r…  r1  r   rS  rp  r  r-   r  r²   r×   Úon_diskru   ÚverbrÁ   s                 r   Úremove_pristine_bundled_skillsrŒ  )  s#  € õ. ÑÔ€HÝ"Ñ$Ô$€KÝÕ3°KÑ@Ô@ÑAÔA€Oà€GØ€Gå# H§N¢NÑ$4Ô$4Ñ5Ô5ð ñ ÑˆˆkØ×!Ò! $Ñ'Ô'ˆØˆ;à�NŠN DÐ4ZÐ[Ð[Ñ\Ô\Ð\ØÝ% c¨;Ñ7Ô7ˆØ�{Š{‰}Œ}ð 	àð #˜t xÐ/Ð/Ø˜T�NØÝ˜D‘/”/ˆØ�kÒ!Ð!Ø�NŠN DÐ4JÐKÐKÑLÔLÐLØàð 	Ø�NŠN˜4Ñ Ô Ð Øð	Ý˜TÑ"Ô"Ð"Ð"øÝ�Ð!ð 	ð 	ð 	Ø�NŠN DÐ4IÀaÐ4IÐ4IÐJÐJÑKÔKÐKØˆHˆHˆHˆHøøøøð	øøøð �8ÐÐØ˜�Ø�Š�tÑÔÐÑàð "�wð "Ý˜Ñ!Ô!Ð!à$Ð3ˆ>ˆ>¨)€DØÐVÐV�˜G™œÐVÐVÅsÈ7Á|Ä|ÐVÐVÐV€Gà˜w°7Ø wðð ð s   Ä	DÄEÄ*E
Å
EÚ__main__z1Syncing bundled skills into ~/.hermes/skills/ ...rË   r  z newr  z updatedr  z
 unchangedr  é   z, z, +z morez user-modified (kept): r   z cleaned from manifestr"  z official optional backfilledz
Done: z. r!  z total bundled.rA  )F)WÚ__doc__r�   r   Úloggingrg   rº   Úsysr   r   Úpathlibr   r   ÚstdoutÚstderrÚ_streamÚhasattrr   r¤   Ú	TypeErrorÚhermes_constantsr   r   r   r(   r   Útypingr   r   r   r   r   Úutilsr   Ú	getLoggerÚ__name__ro   r)  rJ   r8   r*  r   r"   rf   r4   rD   r*   rN   rv   r.   r†   r‰   r–   r§   rª   r®   rµ   r½   rY  rð   rß   rã   rè   rÔ   r  r  r  r>  r,  rW  r.  r_  Úbytesre  r|  r‚  r„  rŒ  r  r@   rç   r¡   rM   ÚMAX_SHOWrb   Úshownr„   rÏ   r   r   r   ú<module>r      sì  ððð ð. €€€Ø €€€Ø €€€Ø 	€	€	€	Ø €€€Ø 
€
€
€
Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'ð ”
˜CœJÐ'ð ð €GØ€wˆw˜Ñ&Ô&ð ð	Ø×Ò¨¸ÐÑCÔCÐCÐCøØ˜IÐ&ð 	ð 	ð 	ØˆDð	øøøðð
 ^Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ð ]Ø 4Ð 4Ð 4Ð 4Ð 4Ð 4Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ø  Ð  Ð  Ð  Ð  Ð  à	ˆÔ	˜8Ñ	$Ô	$€ð ˆoÑÔ€Ø˜8Ñ#€
ØÐ0Ñ0€ð 0Ð ðK˜$ð Kð Kð Kð KðU˜4ð Uð Uð Uð Uð
 S¨¤Xð ð ð ð ð:˜˜S #˜Xœð ð ð ð ð6 ð ð ð ð ð4`˜T # s (œ^ð `ð `ð `ð `ðB˜tð ¨sð °sð ð ð ð ð*¨$ð °4¸¸cÀ4¸iÔ8HÔ3Ið ð ð ð ð2 dð ¸ð À$ð ð ð ð ð˜ð  #ð ð ð ð ð ð ¨Tð °cð ð ð ð ð ð ¨¨c¬ð ð ð ð ð	$˜Tð 	$ cð 	$ð 	$ð 	$ð 	$ð˜t C¨¨s°C¸¨~Ô)>Ð$>Ô?ð ð ð ð ð: $ð °Tð ¸cð ð ð ð ð CHð Dð Dð D¨#ð D¸4ð DÈDð Dð Dð Dð DðN¨T°#°t¸D´z°/Ô-Bð ð ð ð ð( 8<ðð Øðà˜d 3¨¨T¬
 ?Ô3Ô4ðð ˆd„^ðð ð ð ð.mð m¨ð m¸$¸s¼)ð mð mð mð mð`  S¤ð ð ð ð ð0˜d 3¨¨T¬
 ?Ô3ð ð ð ð ð$?Øð?àð?ð ð?ð �s˜D œJ�Ô'ð	?ð
 �3Œxð?ð ð?ð ˆc„]ð?ð ?ð ?ð ?ðDQð Q�tð Q¨ð Qð Qð Qð Qðh.+˜4ð .+ Dð .+ð .+ð .+ð .+ðb`Pð `P˜cð `P¨Dð `P¸Tð `Pð `Pð `Pð `PðF	:¨sð 	:¸sð 	:Àtð 	:ð 	:ð 	:ð 	:ð"¨4°¬:ð "ð "ð "ð "ðJ˜ð  %¨°¬¸À#¼Ð(FÔ"Gð ð ð ð ð&`˜Sð ` Tð `ð `ð `ð `ðF/W¨ð /W°ð /Wð /Wð /Wð /Wðd= 4ð =ð =ð =ð =ð
Cð C¨Dð C¸Tð Cð Cð Cð CðL ˆzÒÑØ	€EÐ
=Ñ>Ô>Ð>Øˆ[˜uÐ%Ñ%Ô%€Fàˆ3ˆv�hÔÑ Ô Ð&Ð&Ð&Øˆ3ˆv�iÔ Ñ!Ô!Ð+Ð+Ð+Ø�)ÔÐ(Ð(Ð(ð€Eð
 ˆoÔð DØ�Ô'ˆØˆØ—	’	˜% 	  	Ô*Ñ+Ô+ˆØˆ3ˆu‰:Œ:˜Ò Ð ØÐ7˜3˜3˜u™:œ:¨Ñ0Ð7Ð7Ð7Ñ7ˆEØ�Š˜˜˜E™
œ
ÐBÐB¸5ÐBÐBÑCÔCÐCØˆiÔð HØ�Š˜˜˜F 9Ô-Ñ.Ô.ÐFÐFÐFÑGÔGÐGØ‡z‚zÐ2Ñ3Ô3ð fØ�Š˜˜˜FÐ#CÔDÑEÔEÐdÐdÐdÑeÔeÐeØ	€EÐ
Q�T—Y’Y˜uÑ%Ô%Ð
QÐ
Q¨°Ô)@Ð
QÐ
QÐ
QÑRÔRÐRÐRÐRð' Ðs   ÁA Á A*Á)A*