§
    ÷žyj²‹  ã                   óB  — U d Z ddlZddlZddlZddlZddlmZ ddlmZm	Z	m
Z
mZmZmZ ddlmZmZmZ  ej        e¦  «        Zdddd	œZ ed
¦  «        Z ed¦  «        ZdZdZdZdZdedee         fd„Zdedefd„Z dedee         fd„Z!ddœdee         defd„Z"ddœdee         defd„Z#da$defd„Z%dedee	eef         ef         fd„Z&dedefd„Z'de	eef         defd„Z( eh d £¦  «        Z)i Z*e	eef         e+d!<   d"edefd#„Z,de	eef         defd$„Z-i Z.e	eee/e/f         e	eef         f         e+d%<   dGd&„Z0de	eef         fd'„Z1dHd(edz  dee         fd)„Z2dee         fd*„Z3i Z4e	eee/f         e
e         f         e+d+<   dGd,„Z5de
e         fd-„Z6de
e         fd.„Z7d/edefd0„Z8defd1„Z9defd2„Z:de	eef         de	ee
f         fd3„Z;de	eef         de
e	eef                  fd4„Z<de
e	eef                  fd5„Z=d6Z>d7e	eef         d8efd9„Z?d:e
e	eef                  de	eef         fd;„Z@d<ZAde	eef         defd=„ZBde	eef         defd>„ZCde	eef         defd?„ZDded@efdA„ZE ejF        dB¦  «        ZGdCedeee         ef         fdD„ZHdEee         defdF„ZIdS )Ia  Lightweight skill metadata utilities shared by prompt_builder and skills_tool.

This module intentionally avoids importing the tool registry, CLI config, or any
heavy dependency chain.  It is safe to import at module level without triggering
tool registration or provider resolution.
é    N)ÚPath)ÚAnyÚDictÚListÚOptionalÚSetÚTuple)Úget_config_pathÚget_skills_dirÚ	is_termuxÚdarwinÚlinuxÚwin32)Úmacosr   Úwindows)z.gitz.githubz.hubz.archivez.venvÚvenvÚnode_moduleszsite-packagesÚ__pycache__z.toxz.noxz.pytest_cachez.mypy_cachez.ruff_cache)Ú
referencesÚ	templatesÚassetsÚscriptsÚ_orgz.active_orgz.org-provenance.jsonz.org-baseline.jsonÚ
skills_dirÚreturnc                 óÎ   — 	 | t           z  t          z  }|                     ¦   «         sdS |                     d¬¦  «                             ¦   «         }|pdS # t
          $ r Y dS w xY w)zBThe org id whose mirror may resolve, or None (no org skills load).Núutf-8©Úencoding)ÚORG_MIRROR_DIR_NAMEÚORG_ACTIVE_MARKERÚexistsÚ	read_textÚstripÚOSError)r   ÚmarkerÚvals      ú7/home/ragecks/.hermes/hermes-agent/agent/skill_utils.pyÚread_active_org_idr)   F   s{   € ðØÕ1Ñ1Õ4EÑEˆØ�}Š}‰Œð 	Ø�4Ø×Ò¨ÐÑ0Ô0×6Ò6Ñ8Ô8ˆØˆ{�dÐøÝð ð ð Øˆtˆtðøøøs   ‚&A ª+A Á
A$Á#A$c                 ó0  — 	 t          | ¦  «                             ¦   «                              t          |¦  «                             ¦   «         ¦  «        }n# t          t          f$ r Y dS w xY wt          |j        ¦  «        o|j        d         t          k    S )z6True when *path* is inside the org mirror (``_org/``).Fr   )r   ÚresolveÚrelative_tor%   Ú
ValueErrorÚboolÚpartsr    ©Úpathr   Úrels      r(   Úis_org_mirror_pathr3   R   sˆ   € ðÝ�4‰jŒj× Ò Ñ"Ô"×.Ò.­t°JÑ/?Ô/?×/GÒ/GÑ/IÔ/IÑJÔJˆˆøÝ•ZÐ ð ð ð Øˆuˆuðøøøå�”	‰?Œ?ÐB˜sœy¨œ|Õ/BÒBÐBó   ‚AA ÁA+Á*A+c                 óV  — 	 t          | ¦  «                             ¦   «                              t          |¦  «                             ¦   «         ¦  «        }n# t          t          f$ r Y dS w xY wt          |j        ¦  «        dk    r#|j        d         t          k    r|j        d         S dS )z@The ``<org_id>`` segment for a path under ``_org/<org_id>/...``.Né   r   é   )r   r+   r,   r%   r-   Úlenr/   r    r0   s      r(   Úorg_id_of_pathr9   [   sž   € ðÝ�4‰jŒj× Ò Ñ"Ô"×.Ò.­t°JÑ/?Ô/?×/GÒ/GÑ/IÔ/IÑJÔJˆˆøÝ•ZÐ ð ð ð Øˆtˆtðøøøå
ˆ3Œ9�~„~˜ÒÐ˜sœy¨œ|Õ/BÒBÐBØŒy˜Œ|ÐØˆ4r4   ©Úrootr;   c                óÎ   — 	 | j         }n3# t          $ r& ddlm}  |t	          | ¦  «        ¦  «        j         }Y nw xY wt          d„ |D ¦   «         ¦  «        pt          | |¬¦  «        S )ax  True if *path* should be skipped by active skill scanners.

    Use this on every ``SKILL.md`` path produced by direct ``rglob`` scans to
    prune dependency, virtualenv, VCS, cache, and progressive-disclosure
    support-package paths. Centralising the check here keeps every
    skill-scanning site in sync with the shared exclusion set.

    Accepts a Path or string.
    r   )ÚPurePathc              3   ó(   K  — | ]}|t           v V — Œd S ©N)ÚEXCLUDED_SKILL_DIRS)Ú.0Úparts     r(   ú	<genexpr>z)is_excluded_skill_path.<locals>.<genexpr>u   s(   è è € Ð=Ð=¨tˆtÕ*Ð*Ð=Ð=Ð=Ð=Ð=Ð=ó    r:   )r/   ÚAttributeErrorÚpathlibr=   ÚstrÚanyÚis_skill_support_path)r1   r;   r/   r=   s       r(   Úis_excluded_skill_pathrJ   f   s™   € ð*Ø”
ˆˆøÝð *ð *ð *Ø$Ð$Ð$Ð$Ð$Ð$Ø��˜T™œÑ#Ô#Ô)ˆˆˆð*øøøõ Ð=Ð=°uÐ=Ñ=Ô=Ñ=Ô=ð ÕAVØ�4ðBñ Bô Bð s   ‚
 Š-:¹:c                ó`  — t          | t          ¦  «        r| nt          t          | ¦  «        ¦  «        }|j        }t	          |dd…         ¦  «        D ][\  }}|t
          vs|dk    rŒt          |d|…         Ž }|�|                     ¦   «         s||z  }|dz                       ¦   «         r dS Œ\dS )a¯  True if *path* is under a support dir of an actual skill root.

    ``references/``, ``templates/``, ``assets/``, and ``scripts/`` are
    progressive-disclosure support areas when they sit directly inside a skill
    directory containing ``SKILL.md``. They are not active discovery roots for
    standalone skills. A preserved package such as
    ``some-skill/references/old-skill-package/SKILL.md`` is documentation data
    unless the caller explicitly loads it via ``file_path``.

    Legitimate categories or skill names such as ``skills/scripts/foo`` remain
    discoverable because their ``scripts`` component is not directly under a
    directory that contains ``SKILL.md``.
    Néÿÿÿÿr   úSKILL.mdTF)Ú
isinstancer   rG   r/   Ú	enumerateÚSKILL_SUPPORT_DIRSÚis_absoluter"   )r1   r;   Úpath_objr/   ÚidxrB   Ú
skill_roots          r(   rI   rI   z   sÈ   € õ " $­Ñ-Ô-ÐBˆtˆtµ4½¸D¹	¼	±?´?€HØŒN€Eõ ˜u S b SœzÑ*Ô*ð ð ‰	ˆˆTØÕ)Ð)Ð)¨S°AªX¨XØÝ˜5  # œ;Ð'ˆ
ØÐ H×$8Ò$8Ñ$:Ô$:ÐØ 
Ñ*ˆJØ˜Ñ#×+Ò+Ñ-Ô-ð 	Ø�4�4ð	àˆ5rD   Úcontentc                 óŠ   ‡‡— t           €,ddlŠt          ‰dd¦  «        p‰j        Šdt          fˆˆfd„}|a t          | ¦  «        S )z7Parse YAML with lazy import and CSafeLoader preference.Nr   ÚCSafeLoaderÚvaluec                 ó2   •— ‰                      | ‰¬¦  «        S )N)ÚLoader)Úload)rX   ÚloaderÚyamls    €€r(   Ú_loadzyaml_load.<locals>._load¤   s   ø€ Ø—9’9˜U¨6�9Ñ2Ô2Ð2rD   )Ú_yaml_load_fnr]   ÚgetattrÚ
SafeLoaderrG   )rU   r^   r\   r]   s     @@r(   Ú	yaml_loadrb   œ   sl   øø€ õ ÐØˆˆˆå˜˜}¨dÑ3Ô3ÐF°t´ˆð	3�ð 	3ð 	3ð 	3ð 	3ð 	3ð 	3ð 	3ð ˆÝ˜Ñ!Ô!Ð!rD   c                 ó–  — i }|                       d¦  «        r
| dd…         } | }|                       d¦  «        s||fS t          j        d| dd…         ¦  «        }|s||fS | d|                     ¦   «         dz   …         }| |                     ¦   «         dz   d…         }	 t          |¦  «        }t          |t          ¦  «        r|}n�# t          $ rt | 	                    ¦   «          
                    d¦  «        D ]I}d|vrŒ| 
                    dd¦  «        \  }}| 	                    ¦   «         || 	                    ¦   «         <   ŒJY nw xY w||fS )	uý  Parse YAML frontmatter from a markdown string.

    Uses yaml with CSafeLoader for full YAML support (nested metadata, lists)
    with a fallback to simple key:value splitting for robustness.

    A single leading UTF-8 BOM (U+FEFF) is stripped before parsing. Windows
    GUI editors (Notepad, PowerShell ``>``) prepend one when saving a SKILL.md
    as UTF-8, and ``read_text(encoding="utf-8")`` preserves it (only
    ``utf-8-sig`` strips it). Left in place, the BOM defeats the ``---`` fence
    check below and the whole frontmatter is silently discarded â€” name,
    description, ``platforms`` gating, env-var setup, and conditional
    activation all vanish. See CONTRIBUTING.md "File encoding".

    Returns:
        (frontmatter_dict, remaining_body)
    u   ï»¿r7   Nz---z
\n---\s*\né   ú
ú:)Ú
startswithÚreÚsearchÚstartÚendrb   rN   ÚdictÚ	Exceptionr$   Úsplit)	rU   ÚfrontmatterÚbodyÚ	end_matchÚyaml_contentÚparsedÚlineÚkeyrX   s	            r(   Úparse_frontmatterrv   ®   s€  € ð" #%€Kð ×Ò˜(Ñ#Ô#ð Ø˜!˜"˜"”+ˆØ€Dà×Ò˜eÑ$Ô$ð !Ø˜DÐ Ð å”	˜-¨°°°¬Ñ5Ô5€IØð !Ø˜DÐ Ð à˜1˜yŸšÑ0Ô0°1Ñ4Ð4Ô5€LØ�9—=’=‘?”? QÑ&Ð(Ð(Ô)€Dð
5Ý˜<Ñ(Ô(ˆÝ�f�dÑ#Ô#ð 	!Ø ˆKøøÝð 5ð 5ð 5à ×&Ò&Ñ(Ô(×.Ò.¨tÑ4Ô4ð 	5ð 	5ˆDØ˜$ˆˆØØŸš C¨Ñ+Ô+‰JˆC�Ø',§{¢{¡}¤}ˆK˜Ÿ	š	™œÑ$Ð$ð		5ð 	5ð5øøøð ˜ÐÐs   Â&C ÃA;EÅEÚ	platformsc                 óp  — | sdS t          | t          ¦  «        s| g} t          j        }t	          ¦   «         }| D ]|}t          |¦  «                             ¦   «                              ¦   «         }t           	                    ||¦  «        }| 
                    |¦  «        r dS |r	|dk    r dS |r|dv r dS Œ}dS )z?Return True when *platforms* is compatible with the current OS.Tr   )ÚtermuxÚandroidF)rN   ÚlistÚsysÚplatformr   rG   Úlowerr$   ÚPLATFORM_MAPÚgetrg   )rw   ÚcurrentÚrunning_in_termuxr}   Ú
normalizedÚmappeds         r(   Úskill_matches_platform_listr…   â   sØ   € àð ØˆtÝ�i¥Ñ&Ô&ð  Ø�Kˆ	ÝŒl€GÝ!™œÐØð ð ˆÝ˜‘]”]×(Ò(Ñ*Ô*×0Ò0Ñ2Ô2ˆ
Ý×!Ò! *¨jÑ9Ô9ˆØ×Ò˜fÑ%Ô%ð 	Ø�4�4ð
 ð 	 ¨7Ò!2Ð!2Ø�4�4àð 	 Ð+@Ð!@Ð!@Ø�4�4øØˆ5rD   ro   c                 óF   — t          |                      d¦  «        ¦  «        S )av  Return True when the skill is compatible with the current OS.

    Skills declare platform requirements via a top-level ``platforms`` list
    in their YAML frontmatter::

        platforms: [macos]          # macOS only
        platforms: [macos, linux]   # macOS and Linux

    If the field is absent or empty the skill is compatible with **all**
    platforms (backward-compatible default).

    Termux note: on Termux/Android, ``sys.platform`` is ``"linux"`` on
    older Pythons but became ``"android"`` on Python 3.13+. Termux is a
    Linux userland riding on the Android kernel, so skills tagged
    ``linux`` are treated as compatible in Termux regardless of which
    ``sys.platform`` value Python reports. Individual Linux commands
    inside a skill may still misbehave (no systemd, BusyBox utils, no
    apt/dnf, etc.) but that is on the skill, not on platform gating.
    rw   )r…   r€   )ro   s    r(   Úskill_matches_platformr‡   û   s   € õ( ' {§¢°{Ñ'CÔ'CÑDÔDÐDrD   >   Ús6ÚdockerÚkanbanÚ_ENV_DETECT_CACHEÚenvc                 óF  — | dk    r| t           v rt           |          S d}| dk    r„t          j        d¦  «        st          j        d¦  «        r$	 ddlm}  |¦   «         }n# t
          $ r d}Y nw xY wd}|rd}nŸ	 ddlm} t           |¦   «         ¦  «        }n€# t
          $ r d}Y nrw xY w| d	k    r$	 dd
l	m
}  |¦   «         }nV# t
          $ r d}Y nHw xY w| dk    r>t          j                             d¦  «        pt          j                             d¦  «        }|t           | <   |S )aq  Return True when the named runtime environment is currently active.

    Cached per process, EXCEPT ``kanban``: that verdict is context-dependent
    (a delegate_task child or an in-process cron job sees the worker's
    HERMES_KANBAN_* vars without owning them), so caching it process-wide would
    freeze whichever context asked first and leak it to the others.
    rŠ   TÚHERMES_KANBAN_TASKÚHERMES_KANBAN_BOARDr   )Ú"is_dispatcher_owned_worker_contextF)Ú_profile_has_kanban_toolsetr‰   )Úis_containerrˆ   z/run/s6z/package/admin/s6-overlay)r‹   ÚosÚgetenvÚagent.delegation_contextr�   rm   Útools.kanban_toolsr‘   r.   Úhermes_constantsr’   r1   Úisdir)rŒ   Úresultr�   Ú_owns_dispatcher_taskr‘   r’   s         r(   Ú_detect_environmentr›   !  s½  € ð ˆh‚€˜3Õ"3Ð3Ð3Ý  Ô%Ð%à€FØ
ˆh‚€õ Œ9Ð)Ñ*Ô*ð 	*­b¬iÐ8MÑ.NÔ.Nð 	*ð-ðð ð ð ð ð ð )KÐ(JÑ(LÔ(LÐ%Ð%øÝð -ð -ð -Ø(,Ð%Ð%Ð%ð-øøøð %*Ð!Ø ð 	ØˆFˆFðØJÐJÐJÐJÐJÐJåÐ9Ð9Ñ;Ô;Ñ<Ô<��øÝð ð ð Ø���ðøøøà	�Šˆð	Ø5Ð5Ð5Ð5Ð5Ð5à!�\‘^”^ˆFˆFøÝð 	ð 	ð 	ØˆFˆFˆFð	øøøà	�Šˆõ
 ”—’˜yÑ)Ô)ð 
­R¬W¯]ª]Ø'ñ.
ô .
ˆð $Õ�cÑØ€Ms6   ÁA ÁA.Á-A.Á9B ÂB&Â%B&Â0C ÃCÃCc                 ó  — |                       d¦  «        }|sdS t          |t          ¦  «        s|g}|D ]V}t          |¦  «                             ¦   «                              ¦   «         }|sŒ8|t          vr dS t          |¦  «        r dS ŒWdS )uR  Return True when the skill is relevant to the current runtime environment.

    Skills may declare an ``environments`` list in their YAML frontmatter::

        environments: [kanban]        # only relevant when kanban is active
        environments: [s6]            # only relevant inside the s6 Docker image
        environments: [docker]        # only relevant inside any container

    If the field is absent or empty the skill is relevant in **all**
    environments (backward-compatible default).

    This is an OFFER-time filter: it controls whether a skill shows up in the
    skills index / autocomplete / slash-command list. It is intentionally NOT
    enforced by ``skill_view`` or ``--skills`` preloading â€” an explicit load is
    explicit consent, and load-bearing force-loads (e.g. a dispatcher pinning
    a task to a specialist skill via ``--skills``) must always succeed
    regardless of how the offer surfaces filter the skill.

    A skill matches when ANY of its declared environments is currently active
    (OR semantics, mirroring ``platforms``). Unknown env tags fail open.
    ÚenvironmentsTF)r€   rN   r{   rG   r~   r$   Ú_KNOWN_ENVIRONMENTSr›   )ro   r�   rŒ   rƒ   s       r(   Úskill_matches_environmentrŸ   _  sª   € ð, —?’? >Ñ2Ô2€LØð ØˆtÝ�l¥DÑ)Ô)ð &Ø$�~ˆØð ð ˆÝ˜‘X”X—^’^Ñ%Ô%×+Ò+Ñ-Ô-ˆ
Øð 	ØØÕ0Ð0Ð0à�4�4Ý˜zÑ*Ô*ð 	Ø�4�4ð	àˆ5rD   Ú_RAW_CONFIG_CACHEc                  ó8   — t                                ¦   «          dS )u/   Test hook â€” drop the shared raw config cache.N)r    Úclear© rD   r(   Ú_raw_config_cache_clearr¤   Œ  s   € å×ÒÑÔÐÐÐrD   c                  óB  — t          ¦   «         } |                      ¦   «         si S 	 |                      ¦   «         }t          | ¦  «        |j        |j        f}n# t          $ r d}Y nw xY w|�t                               |¦  «        }|�|S 	 t          |  
                    d¬¦  «        ¦  «        }n5# t          $ r(}t                               d| |¦  «         i cY d}~S d}~ww xY wt          |t          ¦  «        si S |�#t                               ¦   «          |t          |<   |S )a  Read config.yaml with a shared mtime+size keyed cache.

    This module intentionally avoids importing ``hermes_cli.config`` on the
    skill prompt/build path. A tiny local cache gives the same repeated-read
    win without pulling the heavier CLI config stack into startup.
    Nr   r   z"Could not read skill config %s: %s)r
   r"   ÚstatrG   Úst_mtime_nsÚst_sizer%   r    r€   rb   r#   rm   ÚloggerÚdebugrN   rl   r¢   )Úconfig_pathr¦   Ú	cache_keyÚcachedrs   Úes         r(   Ú_load_raw_configr¯   ‘  sN  € õ "Ñ#Ô#€KØ×ÒÑÔð Øˆ	ðØ×ÒÑ!Ô!ˆÝ˜Ñ%Ô% tÔ'7¸¼ÐFˆ	ˆ	øÝð ð ð Øˆ	ˆ	ˆ	ðøøøð ÐÝ"×&Ò& yÑ1Ô1ˆØÐØˆMðÝ˜;×0Ò0¸'Ð0ÑBÔBÑCÔCˆˆøÝð ð ð Ý�ŠÐ9¸;ÈÑJÔJÐJØˆ	ˆ	ˆ	ˆ	ˆ	ˆ	øøøøðøøøõ �f�dÑ#Ô#ð Øˆ	àÐÝ×ÒÑ!Ô!Ð!Ø'-Õ˜)Ñ$Ø€Ms/   ¦0A ÁA&Á%A&Â
#B. Â.
C Â8CÃC ÃC r}   c                 óÄ  — t          ¦   «         }|st          ¦   «         S |                     d¦  «        }t          |t          ¦  «        st          ¦   «         S ddlm} | pt          j        d¦  «        p
 |d¦  «        }t          |                     d¦  «        ¦  «        }|r>|                     d¦  «        pi                      |¦  «        }|�|t          |¦  «        z  S |S )a
  Read disabled skill names from config.yaml.

    Args:
        platform: Explicit platform name (e.g. ``"telegram"``).  When
            *None*, resolves from ``HERMES_PLATFORM`` or
            ``HERMES_SESSION_PLATFORM`` env vars.  Returns the global
            disabled list, unioned with the platform-specific list when a
            platform is resolved (a globally-disabled skill stays disabled
            on every platform).

    Reads the config file directly (no CLI config imports) to stay
    lightweight.
    Úskillsr   )Úget_session_envÚHERMES_PLATFORMÚHERMES_SESSION_PLATFORMÚdisabledÚplatform_disabled)
r¯   Úsetr€   rN   rl   Úgateway.session_contextr²   r“   r”   Ú_normalize_string_set)r}   rs   Ú
skills_cfgr²   Úresolved_platformÚglobal_disabledr¶   s          r(   Úget_disabled_skill_namesr½   ´  sþ   € õ ÑÔ€FØð Ý‰uŒuˆà—’˜HÑ%Ô%€JÝ�j¥$Ñ'Ô'ð Ý‰uŒuˆà7Ð7Ð7Ð7Ð7Ð7àð 	6ÝŒ9Ð&Ñ'Ô'ð	6àˆ?Ð4Ñ5Ô5ð õ
 ,¨J¯NªN¸:Ñ,FÔ,FÑGÔG€OØð NØ'Ÿ^š^Ð,?Ñ@Ô@ÐFÀB×KÒKØñ
ô 
Ðð Ð(Ø"Õ%:Ð;LÑ%MÔ%MÑMÐMØÐrD   c                 ój   — | €t          ¦   «         S t          | t          ¦  «        r| g} d„ | D ¦   «         S )Nc                 ó’   — h | ]D}t          |¦  «                             ¦   «         ¯#t          |¦  «                             ¦   «         ’ŒES r£   )rG   r$   )rA   Úvs     r(   ú	<setcomp>z(_normalize_string_set.<locals>.<setcomp>ß  s9   € Ð=Ð=Ð=˜q­c°!©f¬f¯lªl©n¬nÐ=�C�‰FŒF�LŠL‰NŒNÐ=Ð=Ð=rD   )r·   rN   rG   )Úvaluess    r(   r¹   r¹   Ú  s=   € Ø€~Ý‰uŒuˆÝ�&�#ÑÔð Ø�ˆØ=Ð= FÐ=Ñ=Ô=Ð=rD   Ú_EXTERNAL_DIRS_CACHEc                  óT   — t                                ¦   «          t          ¦   «          dS )u(   Test hook â€” drop the in-process cache.N)rÃ   r¢   r¤   r£   rD   r(   Ú_external_dirs_cache_clearrÅ   í  s&   € å×ÒÑ Ô Ð ÝÑÔÐÐÐrD   c                  óP  — t          ¦   «         } |                      ¦   «         sg S 	 |                      ¦   «         }t          | ¦  «        |j        f}n# t
          $ r d}Y nw xY w|�+t                               |¦  «        }|�t          |¦  «        S t          ¦   «         }|sg S |                     d¦  «        }t          |t          ¦  «        sg S |                     d¦  «        }|sg }|�t          |¦  «        t          |<   |S t          |t          ¦  «        r|g}t          |t          ¦  «        sg S ddlm}  |¦   «         }	t          ¦   «                              ¦   «         }
t!          ¦   «         }g }|D �]}t          |¦  «                             ¦   «         }|sŒ't$          j                             t$          j                             |¦  «        ¦  «        }t-          |¦  «        }|                     ¦   «         s|	|z                       ¦   «         }n|                     ¦   «         }||
k    rŒ¹||v rŒ¾|                     ¦   «         r+|                     |¦  «         |                     |¦  «         Œýt6                               d|¦  «         �Œ|�t          |¦  «        t          |<   |S )u3  Read ``skills.external_dirs`` from config.yaml and return validated paths.

    Each entry is expanded (``~`` and ``${VAR}``) and resolved to an absolute
    path.  Only directories that actually exist are returned.  Duplicates and
    paths that resolve to the local ``~/.hermes/skills/`` are silently skipped.

    Cached in-process, keyed on ``config.yaml`` mtime â€” the function is
    called once per skill during banner / tool-registry scans, and YAML
    parsing a non-trivial config dominates ``hermes`` cold-start time
    when the cache is absent.
    Nr±   Úexternal_dirsr   )Úget_hermes_homez0External skills dir does not exist, skipping: %s)r
   r"   r¦   rG   r§   r%   rÃ   r€   r{   r¯   rN   rl   r—   rÈ   r   r+   r·   r$   r“   r1   Ú
expanduserÚ
expandvarsr   rQ   Úis_dirÚaddÚappendr©   rª   )r«   r¦   r¬   r­   rs   rº   Úraw_dirsr™   rÈ   Úhermes_homeÚlocal_skillsÚseenÚentryÚexpandedÚps                  r(   Úget_external_skills_dirsrÕ   ó  s®  € õ "Ñ#Ô#€KØ×ÒÑÔð Øˆ	ðØ×ÒÑ!Ô!ˆÝ&)¨+Ñ&6Ô&6¸Ô8HÐ%Iˆ	ˆ	øÝð ð ð Øˆ	ˆ	ˆ	ðøøøð ÐÝ%×)Ò)¨)Ñ4Ô4ˆØÐå˜‘<”<ÐåÑÔ€FØð Øˆ	à—’˜HÑ%Ô%€JÝ�j¥$Ñ'Ô'ð Øˆ	à�~Š~˜oÑ.Ô.€HØð ØˆØÐ Ý.2°6©l¬lÕ  Ñ+ØˆÝ�(�CÑ Ô ð Ø�:ˆÝ�h¥Ñ%Ô%ð Øˆ	à0Ð0Ð0Ð0Ð0Ð0à!�/Ñ#Ô#€KÝ!Ñ#Ô#×+Ò+Ñ-Ô-€LÝ‘e”e€DØ€Fàð Pñ PˆÝ�E‘
”
× Ò Ñ"Ô"ˆØð 	Øå”7×%Ò%¥b¤g×&8Ò&8¸Ñ&?Ô&?Ñ@Ô@ˆÝ�‰NŒNˆà�}Š}‰Œð 	Ø˜q‘×)Ò)Ñ+Ô+ˆAˆAà—	’	‘”ˆAØ�ÒÐØØ�ˆ9ˆ9ØØ�8Š8‰:Œ:ð 	PØ�HŠH�Q‰KŒKˆKØ�MŠM˜!ÑÔÐÐå�LŠLÐKÈQÑOÔOÐOÑOàÐÝ*.¨v©,¬,Õ˜YÑ'Ø€Ms   ¦*A ÁA ÁA c                  óf   — t          ¦   «         g} |                      t          ¦   «         ¦  «         | S )uî   Return all skill directories: local ``~/.hermes/skills/`` first, then external.

    The local dir is always first (and always included even if it doesn't exist
    yet â€” callers handle that).  External dirs follow in config order.
    )r   ÚextendrÕ   )Údirss    r(   Úget_all_skills_dirsrÙ   F  s0   € õ ÑÔÐ€DØ‡K‚KÕ(Ñ*Ô*Ñ+Ô+Ð+Ø€KrD   Ú
identifierc                 ó  — | pd                      ¦   «         }|s|S t          |¦  «                             ¦   «         }|                     ¦   «         s|                     d¦  «        S 	 ddlm} t          |j        ¦  «        }n# t          $ r t          ¦   «         }Y nw xY w|g}	 | 
                    t          ¦   «         ¦  «         n# t          $ r Y nw xY w|D ]6}	 t          |                     |¦  «        ¦  «        c S # t          $ r Y Œ3w xY w	 t          |                     ¦   «                              |                     ¦   «         ¦  «        ¦  «        S # t          $ r  t                                d|¦  «         |cY S w xY w)aŒ  Normalize a skill identifier to a ``skill_view()``-safe relative path.

    Slash commands and cron jobs may store absolute paths to skills that live
    under ``~/.hermes/skills/`` (including via symlinks) or configured
    ``skills.external_dirs``. ``skill_view()`` rejects absolute names for
    security, so callers must translate trusted absolute paths to their
    relative form first.
    Ú ú/r   )Úskills_toolu~   Skill identifier %r is an absolute path outside trusted skills roots â€” passing through unchanged (skill_view will reject it))r$   r   rÉ   rQ   ÚlstripÚtoolsrÞ   Ú
SKILLS_DIRrm   r   r×   rÕ   rG   r,   r-   r+   r©   rª   )rÚ   Úraw_identifierÚidentifier_pathÚ_skills_toolÚprimary_rootÚtrusted_rootsr;   s          r(   Únormalize_skill_lookup_namerç   Q  sá  € ð !Ð& B×-Ò-Ñ/Ô/€NØð ØÐå˜>Ñ*Ô*×5Ò5Ñ7Ô7€OØ×&Ò&Ñ(Ô(ð *Ø×$Ò$ SÑ)Ô)Ð)ð(Ø5Ð5Ð5Ð5Ð5Ð5Ý˜LÔ3Ñ4Ô4ˆˆøÝð (ð (ð (Ý%Ñ'Ô'ˆˆˆð(øøøð "�N€MðØ×ÒÕ5Ñ7Ô7Ñ8Ô8Ð8Ð8øÝð ð ð Øˆðøøøð ð ð ˆð	Ý�×2Ò2°4Ñ8Ô8Ñ9Ô9Ð9Ð9Ð9øÝð 	ð 	ð 	ØˆHð	øøøðÝ�?×*Ò*Ñ,Ô,×8Ò8¸×9MÒ9MÑ9OÔ9OÑPÔPÑQÔQÐQøÝð ð ð Ý�ŠðNàñ	
ô 	
ð 	
ð
 ÐÐÐðøøøsI   Á&B ÂBÂBÂ#!C Ã
CÃCÃ!C>Ã>
DÄ
DÄAE Å'E?Å>E?c                 ó0  — t          | t          ¦  «        r| nt          t          | ¦  «        ¦  «        }	 |                     ¦   «                              ¦   «         S # t
          t          f$ r) |                     ¦   «                              ¦   «         cY S w xY wr?   )rN   r   rG   rÉ   r+   r%   ÚRuntimeErrorÚabsolute)r1   rR   s     r(   Ú_resolve_for_skill_ownershiprë   Š  s�   € Ý! $­Ñ-Ô-ÐBˆtˆtµ4½¸D¹	¼	±?´?€Hð0Ø×"Ò"Ñ$Ô$×,Ò,Ñ.Ô.Ð.øÝ•\Ð"ð 0ð 0ð 0Ø×"Ò"Ñ$Ô$×-Ò-Ñ/Ô/Ð/Ð/Ð/ð0øøøs   µ%A Á7BÂBc                 ó´   — t          | ¦  «        }t          ¦   «         D ]9}t          |¦  «        }	 |                     |¦  «          dS # t          $ r Y Œ6w xY wdS )a·  Return True when ``path`` lives under a configured external skills dir.

    ``skills.external_dirs`` are externally owned: Hermes can discover and view
    their skills, and foreground user-directed tool calls may still edit them,
    but autonomous lifecycle maintenance must treat them as read-only. This
    helper centralizes the ownership boundary so curator/reporting/tool paths do
    not each need to re-interpret the config.
    TF)rë   rÕ   r,   r-   )r1   Ú	candidater;   Úresolved_roots       r(   Úis_external_skill_pathrï   ’  sx   € õ -¨TÑ2Ô2€IÝ(Ñ*Ô*ð ð ˆÝ4°TÑ:Ô:ˆð	Ø×!Ò! -Ñ0Ô0Ð0Ø�4�4øÝð 	ð 	ð 	ØˆHð	øøøàˆ5s   °AÁ
AÁAc                 ód  — |                       d¦  «        }t          |t          ¦  «        si }|                      d¦  «        pi }t          |t          ¦  «        si }|                      dg ¦  «        |                      dg ¦  «        |                      dg ¦  «        |                      dg ¦  «        dœS )z>Extract conditional activation fields from parsed frontmatter.ÚmetadataÚhermesÚfallback_for_toolsetsÚrequires_toolsetsÚfallback_for_toolsÚrequires_tools)ró   rô   rõ   rö   )r€   rN   rl   )ro   rñ   rò   s      r(   Úextract_skill_conditionsr÷   ©  s®   € à�Š˜zÑ*Ô*€Hå�h¥Ñ%Ô%ð ØˆØ�\Š\˜(Ñ#Ô#Ð) r€FÝ�f�dÑ#Ô#ð Øˆà!'§¢Ð,CÀRÑ!HÔ!HØ#ŸZšZÐ(;¸RÑ@Ô@Ø$ŸjšjÐ)=¸rÑBÔBØ Ÿ*š*Ð%5°rÑ:Ô:ð	ð ð rD   c                 óÔ  — |                       d¦  «        }t          |t          ¦  «        sg S |                      d¦  «        }t          |t          ¦  «        sg S |                      d¦  «        }|sg S t          |t          ¦  «        r|g}t          |t          ¦  «        sg S g }t	          ¦   «         }|D �]3}t          |t          ¦  «        sŒt          |                      dd¦  «        ¦  «                             ¦   «         }|r||v rŒUt          |                      dd¦  «        ¦  «                             ¦   «         }|sŒ�||dœ}	|                      d¦  «        }
|
�|
|	d<   |                      d
¦  «        }t          |t
          ¦  «        r,|                     ¦   «         r|                     ¦   «         |	d
<   n||	d
<   |                     |¦  «         |                     |	¦  «         �Œ5|S )a   Extract config variable declarations from parsed frontmatter.

    Skills declare config.yaml settings they need via::

        metadata:
          hermes:
            config:
              - key: wiki.path
                description: Path to the LLM Wiki knowledge base directory
                default: "~/wiki"
                prompt: Wiki directory path

    Returns a list of dicts with keys: ``key``, ``description``, ``default``,
    ``prompt``.  Invalid or incomplete entries are silently skipped.
    rñ   rò   Úconfigru   rÜ   Údescription)ru   rú   ÚdefaultNÚprompt)	r€   rN   rl   r{   r·   rG   r$   rÌ   rÍ   )ro   rñ   rò   Úrawr™   rÑ   Úitemru   ÚdescrÒ   rû   Úprompt_texts               r(   Úextract_skill_config_varsr  ½  sô  € ð  �Š˜zÑ*Ô*€HÝ�h¥Ñ%Ô%ð Øˆ	Ø�\Š\˜(Ñ#Ô#€FÝ�f�dÑ#Ô#ð Øˆ	Ø
�*Š*�XÑ
Ô
€CØð Øˆ	Ý�#•tÑÔð ØˆeˆÝ�c�4Ñ Ô ð Øˆ	à#%€FÝ‘”€DØð ñ ˆÝ˜$¥Ñ%Ô%ð 	ØÝ�$—(’(˜5 "Ñ%Ô%Ñ&Ô&×,Ò,Ñ.Ô.ˆØð 	�c˜T�k�kØå�4—8’8˜M¨2Ñ.Ô.Ñ/Ô/×5Ò5Ñ7Ô7ˆØð 	ØàØð!
ð !
ˆð —(’(˜9Ñ%Ô%ˆØÐØ&ˆE�)ÑØ—h’h˜xÑ(Ô(ˆÝ�k¥3Ñ'Ô'ð 	#¨K×,=Ò,=Ñ,?Ô,?ð 	#Ø)×/Ò/Ñ1Ô1ˆE�(‰OˆOà"ˆE�(‰OØ�Š�‰ŒˆØ�Š�eÑÔÐÑØ€MrD   c                  ór  — g } t          ¦   «         }t          ¦   «         }t          ¦   «         D �]}|                     ¦   «         sŒt	          |d¦  «        D ]ß}	 |                     d¬¦  «        }t          |¦  «        \  }}n# t          $ r Y Œ8w xY w|                     d¦  «        p|j	        j
        }t          |¦  «        |v rŒot          |¦  «        sŒt          |¦  «        }	|	D ]N}
|
d         |vrBt          |¦  «        |
d<   |                      |
¦  «         |                     |
d         ¦  «         ŒOŒà�Œ
| S )aY  Scan all enabled skills and collect their config variable declarations.

    Walks every skills directory, parses each SKILL.md frontmatter, and returns
    a deduplicated list of config var dicts.  Each dict also includes a
    ``skill`` key with the skill name for attribution.

    Disabled and platform-incompatible skills are excluded.
    rM   r   r   Únameru   Úskill)r·   r½   rÙ   rË   Úiter_skill_index_filesr#   rv   rm   r€   Úparentr  rG   r‡   r  rÍ   rÌ   )Úall_varsÚ	seen_keysrµ   r   Ú
skill_filerý   ro   Ú_Ú
skill_nameÚconfig_varsÚvars              r(   Údiscover_all_skill_config_varsr  ø  si  € ð &(€HÝ‘U”U€Iå'Ñ)Ô)€HÝ)Ñ+Ô+ð .ñ .ˆ
Ø× Ò Ñ"Ô"ð 	ØÝ0°¸ZÑHÔHð 	.ð 	.ˆJðØ ×*Ò*°GÐ*Ñ<Ô<�Ý!2°3Ñ!7Ô!7‘�˜Q˜QøÝð ð ð Ø�ðøøøð %Ÿš¨Ñ0Ô0ÐJ°JÔ4EÔ4JˆJÝ�:‰Œ (Ð*Ð*ØÝ)¨+Ñ6Ô6ð Øå3°KÑ@Ô@ˆKØ"ð .ð .�Ø�u”: YÐ.Ð.Ý#& z¡?¤?�C˜‘LØ—O’O CÑ(Ô(Ð(Ø—M’M # e¤*Ñ-Ô-Ð-øð	.ñ	.ð( €Os   Á(BÂ
BÂBzskills.configrù   Ú
dotted_keyc                 ó†   — |                      d¦  «        }| }|D ]&}t          |t          ¦  «        r||v r	||         }Œ$ dS |S )zPWalk a nested dict following a dotted key.  Returns None if any part is missing.ú.N)rn   rN   rl   )rù   r  r/   r�   rB   s        r(   Ú_resolve_dotpathr  %  sZ   € à×Ò˜SÑ!Ô!€EØ€GØð ð ˆÝ�g�tÑ$Ô$ð 	¨°¨¨Ø˜d”mˆGˆGà�4�4Ø€NrD   r  c                 ó¶  — t          ¦   «         }i }| D ]Å}|d         }t          › d|› �}t          ||¦  «        }|�)t          |t          ¦  «        r*|                     ¦   «         s|                     dd¦  «        }t          |t          ¦  «        rDd|v sd|v r<t          j         	                    t          j         
                    |¦  «        ¦  «        }|||<   ŒÆ|S )aV  Resolve current values for skill config vars from config.yaml.

    Skill config is stored under ``skills.config.<key>`` in config.yaml.
    Returns a dict mapping **logical** keys (as declared by skills) to their
    current values (or the declared default if the key isn't set).
    Path values are expanded via ``os.path.expanduser``.
    ru   r  Nrû   rÜ   ú~z${)r¯   ÚSKILL_CONFIG_PREFIXr  rN   rG   r$   r€   r“   r1   rÉ   rÊ   )r  rù   Úresolvedr  Úlogical_keyÚstorage_keyrX   s          r(   Úresolve_skill_config_valuesr  1  sÜ   € õ ÑÔ€Fà!€HØð &ð &ˆØ˜%”jˆÝ,Ð<Ð<¨{Ð<Ð<ˆÝ  ¨Ñ5Ô5ˆàˆ=�Z¨­sÑ3Ô3ˆ=¸E¿KºK¹M¼Mˆ=Ø—G’G˜I rÑ*Ô*ˆEõ �e�SÑ!Ô!ð 	B s¨e | |°t¸u°}°}Ý”G×&Ò&¥r¤w×'9Ò'9¸%Ñ'@Ô'@ÑAÔAˆEà %ˆ�ÑÐà€OrD   é<   c                 óž   — |                       dd¦  «        }|r4t          |¦  «                             ¦   «                              d¦  «        ndS )z@Normalize a skill's description field for comparison/truncation.rú   rÜ   z'")r€   rG   r$   )ro   Úraw_descs     r(   Ú_normalize_skill_descriptionr  T  sE   € à�Š˜}¨bÑ1Ô1€HØ19ÐA�3ˆx‰=Œ=×ÒÑ Ô ×&Ò& uÑ-Ô-Ð-¸rÐArD   c                 ó†   — t          | ¦  «        }|sdS t          |¦  «        t          k    r|dt          dz
  …         dz   S |S )zCExtract a system-prompt-length description from parsed frontmatter.rÜ   Nrd   z...©r  r8   ÚSKILL_PROMPT_DESC_LIMIT©ro   rÿ   s     r(   Úextract_skill_descriptionr"  Z  sO   € å'¨Ñ4Ô4€DØð ØˆrÝ
ˆ4�y„yÕ*Ò*Ð*ØÐ0Õ,¨qÑ0Ð0Ô1°EÑ9Ð9Ø€KrD   c                 óP   — t          | ¦  «        }t          |¦  «        t          k    S )zMTrue when the description will be truncated in the system prompt skill index.r  r!  s     r(   Ú)is_skill_description_truncated_for_promptr$  d  s!   € å'¨Ñ4Ô4€DÝˆt‰9Œ9Õ.Ò.Ð.rD   Úfilenamec              #   ó>  ‡	‡
K  — t          | ¦  «        }t          | ¦  «        Š	t          j                             |t
          ¦  «        }g }t          j        |d¬¦  «        D ]™\  }}}d|v Š
||k    r&t
          |v r‰	€|                     t
          ¦  «         n||k    rˆ	fd„|D ¦   «         |dd…<   ˆ
fd„|D ¦   «         |dd…<   ||v r3|                     t          j                             ||¦  «        ¦  «         Œšt          |¦  «        D ]}t          |¦  «        V — ŒdS )u  Walk skills_dir yielding sorted paths matching *filename*.

    Excludes Hermes metadata, VCS, virtualenv/dependency, cache, and skill
    support directories. Support directories (references/templates/assets/
    scripts) can contain arbitrary markdown and even archived package
    ``SKILL.md`` files, but they are progressive-disclosure data loaded through
    ``skill_view(..., file_path=...)`` rather than active skill roots.

    M2 org mirrors (``_org/``): TOKEN-GATED resolution. Only the active org's
    subdir (per the sync-client-written ``.active_org`` marker) is walked;
    every other ``_org/<id>/`` (stale mirror from a previous org, or no
    marker at all) is pruned â€” leave an org and its skills stop resolving,
    without any manual cleanup.
    T)ÚfollowlinksrM   Nc                 ó    •— g | ]
}|‰k    ¯|‘ŒS r£   r£   )rA   ÚdÚ
active_orgs     €r(   ú
<listcomp>z*iter_skill_index_files.<locals>.<listcomp>†  s   ø€ Ð:Ð:Ð:˜Q¨!¨zª/¨/�q¨/¨/¨/rD   c                 ó<   •— g | ]}|t           vr‰r	|t          v °|‘ŒS r£   )r@   rP   )rA   r)  Úhas_skill_mds     €r(   r+  z*iter_skill_index_files.<locals>.<listcomp>‡  sE   ø€ ð 
ð 
ð 
àØÕ+Ð+Ð+Ø!ð ,Ø&'Õ+=Ð&=Ð&=ð ð '>Ð&=Ð&=rD   )rG   r)   r“   r1   Újoinr    ÚwalkÚremoverÍ   Úsortedr   )r   r%  Úskills_dir_strÚorg_rootÚmatchesr;   rØ   Úfilesr1   r*  r-  s            @@r(   r  r  m  s]  øøè è € õ ˜‘_”_€NÝ# JÑ/Ô/€JÝŒw�|Š|˜NÕ,?Ñ@Ô@€HØ€GÝœW ^ÀÐFÑFÔFð 9ð 9Ñˆˆd�EØ! UÐ*ˆØ�>Ò!Ð!Õ&9¸TÐ&AÐ&AÀjÐFXØ�KŠKÕ+Ñ,Ô,Ð,Ð,Ø�XÒÐà:Ð:Ð:Ð: $Ð:Ñ:Ô:ˆD���‰Gð
ð 
ð 
ð 
àð
ñ 
ô 
ˆˆQˆQˆQ‰ð �uÐÐØ�NŠN�2œ7Ÿ<š<¨¨hÑ7Ô7Ñ8Ô8Ð8øÝ�w‘”ð ð ˆÝ�4‰jŒjÐÐÐÐðð rD   z^[a-zA-Z0-9_-]+$r  c                 óX   — d| vrd| fS t          |                      dd¦  «        ¦  «        S )z~Split ``'namespace:skill-name'`` into ``(namespace, bare_name)``.

    Returns ``(None, name)`` when there is no ``':'``.
    rf   Nr7   )Útuplern   )r  s    r(   Úparse_qualified_namer8  ˜  s3   € ð
 �$€€Ø�TˆzÐÝ�—’˜C Ñ#Ô#Ñ$Ô$Ð$rD   rí   c                 óX   — | sdS t          t                               | ¦  «        ¦  «        S )zDCheck whether *candidate* is a valid namespace (``[a-zA-Z0-9_-]+``).F)r.   Ú_NAMESPACE_REÚmatch)rí   s    r(   Úis_valid_namespacer<  ¢  s+   € àð ØˆuÝ•×#Ò# IÑ.Ô.Ñ/Ô/Ð/rD   )r   Nr?   )JÚ__doc__Úloggingr“   rh   r|   rF   r   Útypingr   r   r   r   r   r	   r—   r
   r   r   Ú	getLoggerÚ__name__r©   r   Ú	frozensetr@   rP   r    r!   ÚORG_PROVENANCE_FILEÚORG_BASELINE_FILErG   r)   r.   r3   r9   rJ   rI   r_   rb   rv   r…   r‡   rž   r‹   Ú__annotations__r›   rŸ   r    Úintr¤   r¯   r½   r¹   rÃ   rÅ   rÕ   rÙ   rç   rë   rï   r÷   r  r  r  r  r  r   r  r"  r$  r  Úcompiler:  r8  r<  r£   rD   r(   ú<module>rH     sÉ  ððð ð ð €€€Ø 	€	€	€	Ø 	€	€	€	Ø 
€
€
€
Ø Ð Ð Ð Ð Ð Ø 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8à GÐ GÐ GÐ GÐ GÐ GÐ GÐ GÐ GÐ Gà	ˆÔ	˜8Ñ	$Ô	$€ð
 ØØðð €ð  �iðñô Ð ð. �YÐOÑPÔPÐ ð Ð Ø!Ð Ø,Ð ð )Ð ð	 4ð 	¨H°S¬Mð 	ð 	ð 	ð 	ðC¨ð C°$ð Cð Cð Cð Cð Tð ¨h°s¬mð ð ð ð ð <@ð ð ð ¨(°4¬.ð ÀDð ð ð ð ð( ;?ð ð ð ¨°$¬ð À4ð ð ð ð ð> €ð"�sð "ð "ð "ð "ð$.˜sð . u¨T°#°s°(¬^¸SÐ-@Ô'Að .ð .ð .ð .ðh¨3ð °4ð ð ð ð ð2E¨¨S°#¨X¬ð E¸4ð Eð Eð Eð EðB  �iÐ :Ð :Ð :Ñ;Ô;Ð à%'Ð �4˜˜T˜	”?Ð 'Ð 'Ñ 'ð;˜Sð ; Tð ;ð ;ð ;ð ;ð|$¨4°°S°¬>ð $¸dð $ð $ð $ð $ðT ACÐ �4˜˜c 3¨˜mÔ,¨d°3¸°8¬nÐ<Ô=Ð BÐ BÑ Bðð ð ð ð
 ˜$˜s C˜xœ.ð  ð  ð  ð  ðF#ð # s¨T¡zð #¸SÀ¼Xð #ð #ð #ð #ðL> S¨¤Xð >ð >ð >ð >ð  ;=Ð �d˜5  c œ?¨D°¬JÐ6Ô7Ð <Ð <Ñ <ðð ð ð ðP $ t¤*ð Pð Pð Pð Pðf˜T $œZð ð ð ð ð6¨Cð 6°Cð 6ð 6ð 6ð 6ðr0¨$ð 0ð 0ð 0ð 0ð Dð ð ð ð ð.¨$¨s°C¨x¬.ð ¸TÀ#ÀtÀ)¼_ð ð ð ð ð(8¨4°°S°¬>ð 8¸dÀ4ÈÈSÈÄ>Ô>Rð 8ð 8ð 8ð 8ðv$¨¨T°#°s°(¬^Ô(<ð $ð $ð $ð $ðT &Ð ð	˜T # s (œ^ð 	¸ð 	ð 	ð 	ð 	ðØ�d˜3 ˜8”nÔ%ðà	ˆ#ˆsˆ(„^ðð ð ð ð@ Ð ðB¨d°3¸°8¬nð BÀð Bð Bð Bð Bð¨4°°S°¬>ð ¸cð ð ð ð ð/¸4ÀÀSÀ¼>ð /Èdð /ð /ð /ð /ð# tð #°sð #ð #ð #ð #ðP �”
Ð.Ñ/Ô/€ð%˜sð % u¨X°c¬]¸CÐ-?Ô'@ð %ð %ð %ð %ð0 (¨3¤-ð 0°Dð 0ð 0ð 0ð 0ð 0ð 0rD   