Ë
    âß²j¢K  ã                  ó4  — d Z ddlmZ ddlZddlZddlmZ ddlm	Z	  ej                  d«      Zdd„Zdd„Zdd	„Zd
ZdZdZdd„Zdd„Zd d„Zd!d„ZdZ	 	 d"	 	 	 	 	 	 	 	 	 d#d„Zddddœ	 	 	 	 	 	 	 	 	 	 	 d$d„Zd%d„Z	 	 	 	 	 	 	 	 d&d„ZddlmZ ddlmZ ddlm Z! y)'a¹  Cron job prompt assembly: context_from injection, skill loading, the assembled-prompt
injection scan, and the credential-exfil / config-block guards.

Split out of ``cron.scheduler``. Import names from this module directly (``cron.scheduler`` only
imports the few it calls itself). Origin-resident helpers and sibling split modules are reached
late-bound (``_sched`` / module refs at the bottom) so monkeypatching the defining module works.
é    )ÚannotationsN)Únow)ÚOptionalzcron.schedulerc                óP  — | xs dj                  «       D �cg c]  }|j                  «       sŒ|‘Œ }}|sy	 t        j                  |d   j                  «       «      }t        |t        «       xs |j                  dd«      duS c c}w # t        j                  t
        f$ r Y yw xY w)u7  Wake gate: False only if the last non-empty stdout line is JSON ``{"wakeAgent": false}``
    (agent skipped entirely â€” no LLM run, no delivery); anything else wakes normally.

    Any other output (non-JSON, missing flag, gate absent, or ``wakeAgent: true``) means wake the agent
    normally. See #1232.
    Ú TéÿÿÿÿÚ	wakeAgentF)	Ú
splitlinesÚstripÚjsonÚloadsÚJSONDecodeErrorÚ
ValueErrorÚ
isinstanceÚdictÚget)Úscript_outputÚlineÚstripped_linesÚgates       ú:/home/ubuntu/.hermes/hermes-agent/cron/scheduler_prompt.pyÚ_parse_wake_gater      s    € ð )6Ò(;¸×'GÑ'GÓ'IÖZ˜tÈTÏZÉZÍ\’dÐZ€NÐZÙØðÜ�z‰z˜.¨Ñ,×2Ñ2Ó4Ó5ˆô ˜$¤Ó%Ð%ÒQ¨¯©°+¸tÓ)DÈEÐ)QÐQùò [øô
 × Ñ ¤*Ð-ò Ùðús   —B­B·&B	 Â	B%Â$B%c                ó   — d|› d|› d|› d| › �S )z:Prefix ``prompt`` with a fenced ``## heading`` data block.z## Ú
z

```
z
```

© )ÚpromptÚheadingÚintroÚbodys       r   Ú_prepend_context_blockr    %   s!   € à��	˜˜E˜7 )¨D¨6°¸6¸(ÐCÐCó    c                ó  — | j                  d«      }|€| j                  d«      }|r|gng }nt        |t        «      r|g}|D �cg c]5  }t        |«      j                  «       sŒt        |«      j                  «       ‘Œ7 c}S c c}w )zVNormalized skill names from ``skills`` (list or str) or the legacy singular ``skill``.ÚskillsÚskill)r   r   Ústrr   )Újobr#   ÚlegacyÚnames       r   Ú_job_skill_namesr)   *   sk   € à�W‰W�XÓ€FØ€~Ø—‘˜Ó!ˆÙ#�&‘¨‰Ü	�FœCÔ	 Ø�ˆØ*0ÖF $´C¸³I·O±OÕ4EŒC�‹I�O‰OÕÒFÐFùÒFs   ÁBÁ#Bi@  zºThe following is this job's most recent non-silent output from a previous run. Use it for continuity: avoid repeating what was already reported, and continue where the last run left off.zgThe following is the most recent output from a preceding cron job. Use it as context for your analysis.c                ó†   — d| vr| S | j                  d«      d   j                  «       }|rt        j                  |«      ry|S )u©  The reusable answer of a stored run: the text after the last ``## Response``.

    Archives without the heading (script-mode runs) stay whole-document. The LAST
    occurrence is the writer's boundary â€” the assembled prompt half can itself carry
    the literal heading (a skill documenting its response format, an injected previous
    answer quoting it), so an early split would re-inject the prompt noise this
    extraction exists to drop.
    ``None`` marks "no usable answer" â€” a blank or silent response (any form the
    delivery lane itself suppresses) â€” so the caller falls through to an older
    archive instead of injecting prompt noise the job already has.
    z## Responseé   N)Ú
rpartitionr   Ú_schedÚ_is_cron_silence_response)ÚarchiveÚanswers     r   Ú_archive_answerr1   B   sG   € ð ˜GÑ#ØˆØ×Ñ Ó.¨qÑ1×7Ñ7Ó9€FÙ”V×5Ñ5°fÔ=ØØ€Mr!   c                ó€   — t        | «      t        k  r| S t        dz  }t        | «      d|z  z
  }| d| › d|› d| | d › �S )zKClip oversized context head+tail; conclusions and summaries sit at the end.r+   Nz

[... z chars omitted ...]

)ÚlenÚ_MAX_CONTEXT_CHARS)ÚtextÚkeepÚomitteds      r   Ú_clip_to_context_budgetr8   V   sV   € ä
ˆ4ƒyÔ&Ò&ØˆÜ Ñ"€DÜ�$‹i˜!˜d™(Ñ"€GØ�5�Dˆkˆ]˜) G 9Ð,CÀDÈ$ÈÈÀLÀ>ÐRÐRr!   c           
     ój  — | j                  d«      }|s|dfS ddlm}  |«       }t        |t        «      r|g}d}|D �]½  }t        |t        «      r?|j                  «       j                  «       dk(  rt	        | j                  d«      xs d«      }|| j                  d«      k(  }|rt        d„ |D «       «      sKt        j                  d	|| j                  d«      | j                  d
«      t        j                  | «      «       ŒÆ	 t        ||z  j                  d«      d„ d¬«      }d}	|D ]“  }
|
j                  d¬«      j                  «       }|j                  dd«      d   j                  dd«      d   }|j!                  d«      xr  t#        d„ |j%                  «       D «       «      }|r|rŒƒt'        |«      }|€Œ‘|}	 n |	s�Œ†t)        |	«      }	|rt+        |dt,        |	«      }nt+        |d|› d�t.        |	«      }d}�ŒÀ ||fS # t0        t2        f$ r"}t        j                  d||«       Y d}~�Œñd}~ww xY w)zWPrepend the latest output of each ``context_from`` job; returns ``(prompt, injected)``.Úcontext_fromFr   )Úget_cron_output_dirÚselfÚidr   c              3  ó$   K  — | ]  }|d v –— Œ
 y­w)Ú0123456789abcdefNr   )Ú.0Úcs     r   ú	<genexpr>z'_inject_context_from.<locals>.<genexpr>o   s   è ø€ Ò'WÀA¨Ð-?Ô(?Ñ'Wùs   ‚z@context_from: skipping invalid job_id %r for job_id=%r name=%r%sr(   z*.mdc                ó6   — | j                  «       j                  S )N)ÚstatÚst_mtime)Úfs    r   ú<lambda>z&_inject_context_from.<locals>.<lambda>x   s   € ÈÏÉË×IZÑIZ€ r!   T)ÚkeyÚreversezutf-8)Úencodingz
---
é   z

## Promptz# Cron Job:c              3  ó>   K  — | ]  }|j                  d «      –— Œ y­w))z**Status:** no_changez**Status:** silentz&Script gate returned `wakeAgent=false`N)Ú
startswith)r@   r   s     r   rB   z'_inject_context_from.<locals>.<genexpr>�   s,   è ø€ ò Kð ð —O‘Oð %O÷ PñKùs   ‚NzYour previous run's outputzOutput from job 'ú'z2context_from: failed to read output for job %r: %s)r   Ú	cron.jobsr;   r   r%   r   ÚlowerÚallÚloggerÚwarningÚ	_deliveryÚ_cron_job_origin_log_suffixÚsortedÚglobÚ	read_textÚsplitrM   Úanyr
   r1   r8   r    Ú_SELF_CONTEXT_INTROÚ_UPSTREAM_CONTEXT_INTROÚOSErrorÚPermissionError)r&   r   r:   r;   Ú
output_dirÚinjectedÚsource_job_idÚis_selfÚoutput_filesÚlatest_outputÚoutput_fileÚ	candidateÚheaderÚsilent_auditr0   Úes                   r   Ú_inject_context_fromrj   _   sU  € à—7‘7˜>Ó*€LÙØ�uˆ}ÐÝ-Ù$Ó&€JÜ�,¤Ô$Ø$�~ˆØ€HØ%ó 2cˆä�m¤SÔ)¨m×.AÑ.AÓ.C×.IÑ.IÓ.KÈvÒ.UÜ §¡¨£Ò 3°Ó4ˆMØ 3§7¡7¨4£=Ñ0ˆá¤CÑ'WÈÔ'WÔ$WÜ�N‰NØRØ˜sŸw™w t›}¨c¯g©g°f«oÜ×5Ñ5°cÓ:ôð
 ð%	cÜ!Ø˜mÑ+×1Ñ1°&Ó9Ñ?ZØôˆLð ˆMØ+ò �Ø'×1Ñ1¸7Ð1ÓC×IÑIÓK�	ð #Ÿ™¨°AÓ6°qÑ9×?Ñ?ÀÈqÓQÐRSÑT�Ø(×3Ñ3°MÓBò  Äsñ Kð !'× 1Ñ 1Ó 3ôKó H�ñ
 !¡LØÜ(¨Ó3�Ø�>ØØ &�Ùð!ñ" !ÙÜ3°MÓBˆMÙÜ/ØÐ8Ô:MÈ}ó^‘ô 0ØÐ/°¨¸aÐ@ÔBYØ!ó�ð ŠHð_2cðf �8ÐÐøô œÐ)ò 	cä�N‰NÐOÐQ^Ð`a×bÒbûð	cús   ÄB=HÇ8HÈH2ÈH-È-H2c           
     ó8  ‡‡‡— ddl m} ddlm} ddlm}m} ddlm} ddl	m
} | j                  d| j                  d«      «      Št        | j                  d«      xs d	«      xs d
}g }	g Šd ˆˆˆfd„}
|D �]  Š |‰j                  d«      «      }|r? ||d	|¬«      }|r(|	r|	j                  d	«       |	j                  |d   «       n	 |
d‰«       Œ\	 t        j                    | |‰«      «      «      }|j                  d«      s! |
d|j                  d«      xs d‰› d�«       Œ°	  |‰|¬«       |	r|	j                  d	«       |	j-                  d‰› d�d	t        |j                  d«      xs d	«      j/                  «       g«        |||	«       �Œ ‰r7|	j1                  dddj3                  ‰«      › ddj3                  ‰«      › d�«       |	S # t        j"                  t$        f$ r  |
d‰«       Y �Œ|w xY w# t&        $ r t(        j+                  d‰d¬«       Y Œèw xY w)!zWLoad each named skill/bundle into prompt parts; unknown ones are skipped with a notice.r   )Ú
skill_view)Úbump_use)Úbuild_bundle_invocation_messageÚresolve_bundle_command_key)Ú_inject_skill_config)Únormalize_skill_lookup_namer(   r=   r   Nc                ó\   •— t        j                  d| z   ‰g|¢­Ž  ‰j                  ‰«       y )NzCron job '%s': )rR   rS   Úappend)ÚmsgÚargsÚ	job_labelÚ
skill_nameÚskippeds     €€€r   Ú_skipz%_load_cron_skill_parts.<locals>._skip«   s(   ø€ Ü�‰Ð(¨3Ñ.°	ÐA¸DÓAØ�‰�zÕ"r!   ú/)Úuser_instructionÚtask_idz/bundle '%s' could not load any skills, skippingz*skill '%s' returned invalid JSON, skippingÚsuccessu    skill not found, skipping â€” %sÚerrorzFailed to load skill 'rN   )r|   z-Cron job: failed to bump skill usage for '%s'T)Úexc_infoz&[IMPORTANT: The user has invoked the "zf" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]Úcontentze[IMPORTANT: The following skill(s) were listed for this job but could not be found and were skipped: z, un   . Start your response with a brief notice so the user is aware, e.g.: 'âš ï¸� Skill(s) not found and skipped: z'])rt   r%   ÚreturnÚNone)Útools.skills_toolrl   Útools.skill_usagerm   Úagent.skill_bundlesrn   ro   Úagent.skill_commandsrp   Úagent.skill_utilsrq   r   r%   Úlstriprs   r   r   r   Ú	TypeErrorÚ	ExceptionrR   ÚdebugÚextendr   ÚinsertÚjoin)r&   Úskill_namesrl   rm   rn   ro   rp   rq   r|   Úpartsry   Ú
bundle_keyÚbundle_payloadÚloadedrv   rw   rx   s                 @@@r   Ú_load_cron_skill_partsr”   Ÿ   s)  ú€ å,Ý*ß_Ý9Ý=Ø—‘˜ §¡¨£Ó.€IÜ�#—'‘'˜$“-Ò% 2Ó&Ò.¨$€GØ€EØ€G÷#ð "ó $,ˆ
á/°
×0AÑ0AÀ#Ó0FÓGˆ
ÙÙ<Ø¨R¸ôBˆNáÙØ—L‘L Ô$Ø—‘˜^¨AÑ.Õ/áÐGÈÔTØð	Ü—Z‘Z¡
Ñ+FÀzÓ+RÓ SÓTˆFð �z‰z˜)Ô$ÙØ2Ø—
‘
˜7Ó#ÒMÐ)?À
¸|È1Ð'MôOð ð	eÙ�Z¨Õ1ñ Ø�L‰L˜ÔØ�‰Ø4°Z°Lð  Agð  hØÜ�—
‘
˜9Ó%Ò+¨Ó,×2Ñ2Ó4ð6ô 	7ñ 	˜V UÖ+ðI$,ñL Ø�‰�Qð!Ø!%§¡¨7Ó!3Ð 4ð 57à7;·y±yÀÓ7IÐ6JÈ"ðNô	ð €Løô; ×$Ñ$¤iÐ0ò 	ÙÐ>À
ÔKÚð	ûô ò 	eÜ�L‰LÐHÈ*Ð_cˆLÖdð	eús$   Ã!GÄ&
G5Ç"G2Ç1G2Ç5!HÈHuo  [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user â€” do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. [SILENT] is a literal ASCII control token â€” never translate or rephrase it, whatever language the rest of your answer uses. Never combine [SILENT] with content â€” either report your findings normally, or say [SILENT] and nothing more. FAILURE: If a delegated child fails and this cron run must be recorded as failed, put [CRON_FAILURE] on the first line by itself, then explain the child failure on following lines. RECURSION: This is a run of an EXISTING scheduled job â€” execute the task now. NEVER create or update a cron job because of recurring or future-schedule language in the task prompt below; treat phrasing like "each Monday" or "every day at 9" as context for this run, not as a request to schedule another job.]

c                ój  — t        | j                  d«      xs d«      }|r|› d|› �}|}d}|r	|› d|› �}d}| j                  d«      }|rl|�|nFt        j                  |t	        j
                  | t        | j                  d«      xs d«      «      ¬	«      \  }}	|r|	sy|rd
nd\  }
}t        ||
||	«      }d}t        | |«      \  }}|xs |}ddlm	} |j                  t        | j                  d«      xs d«      «      }|r|› |› �}d}t        |z   }t        | «      }|st        || d||¬«      S t        | |«      }d}|r ddlm} |j#                  d«        |||«      }t        dj%                  |«      | d¬«      }|r6t'        |«      t'        |«      kD  r|j)                  |«      rddlm}  ||«       |S )uö  Build the effective prompt for a cron job, optionally loading skills first.
    ``prerun_script``: cached ``(success, stdout)`` from a script the caller already ran (wake-gate
    check) â€” skips re-execution. ``extra_prompt``: user-authored per-run ``## Run Context`` for this
    fire only, never persisted to the job. ``runtime_data_prompt`` is operator-configured runtime
    data (such as monitor output) and is scanned as injected data rather than user input.

    When provided, the script is not re-executed and the cached result is used for prompt injection. When
    omitted, the script (if any) runs inline as before. extra_prompt: Optional per-run context (from
    ``cronjob(action='run')``, 57331 â€” salvaged from #57342 by @liuhao1024).
    r   r   z

## Run Context
FTÚscriptNr=   )Úworkdir)zScript OutputzZThe following data was collected by a pre-run script. Use it as context for your analysis.)zScript Errorz;The data-collection script failed. Report this to the user.r   )Únotepad©Ú
has_skillsÚhas_injected_dataÚuser_prompt)Úappend_user_instructionr   )rš   )Úregister_stable_prefix)r%   r   Ú_scriptÚ_run_job_scriptr-   Ú_resolve_job_workdirr    rj   Úcronr˜   Úrender_notepad_sectionÚ
_CRON_HINTr)   Ú_scan_assembled_cron_promptr”   r†   r�   rs   rŽ   r3   rM   Úagent.prompt_cache_boundaryrž   )r&   Úprerun_scriptÚextra_promptÚruntime_data_promptrœ   r   r›   Úscript_pathr}   r   r   r   Ú_ctx_injectedÚcron_notepadÚnotepad_sectionr�   r�   Ústable_prefixr�   Ú	assembledrž   s                        r   Ú_build_job_promptr°   ö   sø  € ô �c—g‘g˜hÓ'Ò-¨2Ó.€KÙØ$˜Ð%9¸,¸ÐHˆØ€Fð ÐÙØ�8Ð/Ð0CÐ/DÐEˆØ Ðà—'‘'˜(Ó#€KÙà*Ð6‰MÜ×(Ñ(Ø¤V×%@Ñ%@ÀÄcÈ#Ï'É'ÐRVË-ÒJ]Ð[]ÓF^Ó%_ôañ 	ˆ�ñ ™=Øñ ñFð añ	 	ˆ�ô (¨°¸ÀÓNˆØ Ðä0°°fÓ=Ñ€FˆMØ)Ò:¨]Ðõ -Ø"×9Ñ9¼#¸c¿g¹gÀd»mÒ>QÈrÓ:RÓS€OÙØ#Ð$ V HÐ-ˆØ Ðä˜&Ñ €FÜ" 3Ó'€KÙÜ*Ø�C EÐ=NØ#ô
ð 	
ô
 # 3¨Ó4€EØ€MÙÝ@Ø�‰�RÔñ 0°°vÓ>ˆÜ+¨D¯I©I°eÓ,<¸cÈdÔS€IáÜ�	‹NœS Ó/Ò/Ø× Ñ  Ô/õ 	GÙ˜}Ô-ØÐr!   Fr™   c               ó  — ddl m} ddlm} |s|r || «      \  } }|s|s|r ||«      }n || «      }|rRt        j                  d|j                  d«      xs |j                  d«      xs d|«       t        j                  |«      ‚| S )uè  Scan the assembled cron prompt for injection; raise ``CronPromptInjectionBlocked`` on a hit.
    Needed because skill content is loaded from disk at runtime (never scanned at create/update)
    and cron auto-approves tool calls. Tier by what the prompt CONTAINS: user prompt + hint only â†’
    STRICT ``_scan_cron_prompt``; skills or injected data â†’ LOOSER ``_scan_cron_skill_assembled``
    (command-shape patterns dropped, invisible unicode sanitized not blocked, so a false positive
    cannot permanently kill a job); injected data without skills also scans ``user_prompt`` STRICT.

    Since cron runs non-interactively (auto-approves tool calls), a malicious skill carrying an injection
    payload bypassed every gate. See #3968.
    r   )Ú_scan_cron_prompt)Ú_scan_cron_skill_assembleduC   Cron job '%s': assembled prompt blocked by injection scanner â€” %sr(   r=   z	<unknown>)	Útools.cronjob_toolsr²   Útools.cronjob_prompt_scanr³   rR   rS   r   r-   ÚCronPromptInjectionBlocked)r¯   r&   rš   r›   rœ   r²   r³   Ú
scan_errors           r   r¥   r¥   I  s…   € õ 6ÝDÙÑ&á :¸9Ó EÑˆ	�:Ù¡*±Ù*¨;Ó7‰Já& yÓ1ˆ
ÙÜ�‰ØQØ�G‰G�F‹OÒ;˜sŸw™w t›}Ò;°¸Zô	Iô ×/Ñ/°
Ó;Ð;ØÐr!   c                ób  — 	 ddl m}  || j                  d«      | j                  d«      «      }|r9| j                  d	«      }t        j                  d
||«       t        d|› d|› �«      ‚y# t        $ r:}| j                  d«      rd|j                  j
                  › d|› d�nd}Y d}~Œzd}~ww xY w)aC  Fail closed (RuntimeError) if the stored provider/base_url pair could exfiltrate a key.
    Runtime backstop: jobs persisted before the create/update guard, or written directly to the
    store, reach provider resolution unchecked. Fallback providers come from operator config and
    are validated by the caller, not here.r   )Ú_validate_cron_base_urlÚproviderÚbase_urlz+could not validate provider/base_url pair (z: z=); refusing to run a job with an unverified base_url overrideNr=   ud   Job '%s': refusing to run â€” unsafe provider/base_url pair could exfiltrate a stored credential: %sz
Cron job 'z' blocked for safety: )	r´   r¹   r   rŠ   Ú	__class__Ú__name__rR   r~   ÚRuntimeError)r&   r¹   ÚerrÚexcÚjob_ids        r   Ú_guard_job_credential_exfilrÂ   h  s¿   € ð

+Ý?Ù% c§g¡g¨jÓ&9¸3¿7¹7À:Ó;NÓOˆñ Ø—‘˜“ˆÜ�‰ð1à�Cô	ô ˜Z¨ xÐ/EÀcÀUÐKÓLÐLð øô ò +ð �W‰W�ZÔ ðØ—‘×&Ñ&Ð' r¨#¨ð /.ñ.ð '+õ	 	ûð+ús   ‚-A+ Á+	B.Á40B)Â)B.c           	     ó  — ddl m} t        j                  d| |«       	  || d|› �«       t        «       j                  d«      }d|› d| › d	|› d
|› d�	}d|› d|› �}d|||fS # t        $ r t        j                  d| «       Y ŒWw xY w)zžFail a run closed and pause the job: an unrunnable job left enabled re-fires every tick
    forever; ``paused_at``/``paused_reason`` give an auditable record.r   )Ú	pause_jobzJob '%s': %szAuto-paused by scheduler: z-Job '%s': failed to auto-pause unrunnable jobz%Y-%m-%d %H:%M:%Sz# Cron Job: z

**Job ID:** z
**Run Time:** u7   
**Status:** blocked (unrunnable job) â€” auto-paused

r   u   âš  Cron job 'z' was auto-paused

F)rO   rÄ   rR   r~   rŠ   Ú	exceptionÚ_hermes_nowÚstrftime)rÁ   Újob_nameÚreasonrÄ   Únow_isoÚdocÚalerts          r   Ú_block_and_pause_jobrÍ   �  s¾   € õ $Ü
‡L�L� ¨Ô0ðRÙ�&Ð6°v°hÐ?Ô@ô ‹m×$Ñ$Ð%8Ó9€Gà
�x�jð !Ø�hð Ø ˜	ð "Càˆ(�"ð		ð ð ˜X˜JÐ&;¸F¸8ÐD€EØ�#�u˜fÐ$Ð$øô ò RÜ×ÑÐHÈ&ÖQðRús   ŸA! Á!BÂB)Ú	scheduler)Úscheduler_delivery)Úscheduler_script)r   r%   r�   Úbool)
r   r%   r   r%   r   r%   r   r%   r�   r%   )r&   r   r�   ú	list[str])r/   r%   r�   z
str | None)r5   r%   r�   r%   )r&   r   r   r%   r�   ztuple[str, bool])r&   r   r�   rÒ   r�   rÒ   )NNN)
r&   r   r§   zOptional[tuple]r¨   úOptional[str]r©   rÓ   r�   r%   )r¯   r%   r&   r   rš   rÑ   r›   rÑ   rœ   rÓ   r�   r%   )r&   r   r�   r‚   )rÁ   r%   rÈ   r%   rÉ   r%   r�   z$tuple[bool, str, str, Optional[str]])"Ú__doc__Ú
__future__r   r   ÚloggingÚhermes_timer   rÆ   Útypingr   Ú	getLoggerrR   r   r    r)   r4   r[   r\   r1   r8   rj   r”   r¤   r°   r¥   rÂ   rÍ   r¢   rÎ   r-   rÏ   rT   rÐ   rŸ   r   r!   r   ú<module>rÚ      s8  ðñõ #ã Û Ý *Ý ð 
ˆ×	Ñ	Ð+Ó	,€óRó"Dó
Gð Ð ðð ðð óó(Só=ó@=ðBKð ð0 UYØ)-ðPØ	ðPØ-ðPØDQðPà&ðPð 	óPðh 6;ÐV[Ø!%ñØðØðØ.2ðØOSðàðð 	óó>Mð2%Øð%Øð%Ø(+ð%Ø0Tó%õ2 %Ý 0Þ ,r!   