
    *"hj1O                       d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ dd	lmZ  ej                  e      Zd
ZdZdZdaddZddZ	 	 	 	 	 	 	 	 ddZddZdddZdddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 d dZd!dZy)"a  
Session-level execution helpers for the current evolve_server pipeline.

The active flow is intentionally small:
- merge same-name conflicts when two evolved versions collide
- evolve an existing skill from aggregated session evidence
- create a brand-new skill from no-skill session groups

Older turn-level attribution / decision / execution prompts were removed so
`evolve_server` matches the session-level pipeline used by `server.py`.
    )annotationsN)Path)Optional   )DecisionAction)AsyncLLMClient)parse_single_skilla4  You are a skill engineer for SkillClaw.

Two versions of the SAME skill exist because separate evolution actions produced different content under the same name.

Your task: merge the two versions into a single, superior version that combines the best parts of both.

## Merge principles

- Preserve ALL actionable guidance from both versions - do not drop useful content.
- Eliminate redundancy - deduplicate overlapping sections.
- If the two versions contradict each other, prefer the more specific or concrete guidance.
- Preserve the stronger existing structure unless reorganization is clearly beneficial.
- Do not rewrite either version just to make it look more standardized.
- Keep the same name.
- The merged description should cover trigger conditions from both versions.
- Only keep metadata or extra frontmatter that still helps the merged skill.
- The merged content should stay concise, but do not force a rigid section template.

## Output format

Return EXACTLY one JSON object with:
- "name": same name
- "description": merged trigger description
- "content": merged Markdown body only, not a full SKILL.md with frontmatter

Optional fields:
- "metadata": merged metadata when genuinely useful
- "extra_frontmatter": preserved or merged extra frontmatter when justified

No markdown fences. Output ONLY valid JSON.
a  You are a skill engineer for SkillClaw's skill evolution system.

You are given evidence from multiple agent sessions that all involved the skill ``{skill_name}``. Each session contains a programmatic trajectory (step-by-step tool calls and outcomes) and an LLM-generated analysis.

Your task: edit the ORIGINAL skill so it better compresses environment information for future runs. Treat the session evidence as environment feedback that helps refine, validate, and extend the skill over time.

Analyze the session evidence alongside the current skill content, then decide the best course of action:

1. **improve_skill** - The skill content needs targeted edits based on the session evidence (for example missing guidance, outdated information, or unclear instructions). Produce the updated skill.

2. **optimize_description** - The skill body content is fine, but its description causes it to be matched to wrong tasks. Rewrite ONLY the description for more precise triggering. Do NOT change the body content.

3. **create_skill** - The session evidence reveals a recurring pattern, capability gap, or reusable strategy that does NOT belong in the current skill ``{skill_name}``. A brand-new, separate skill is needed. The current skill remains unchanged. Only choose this when the pattern is clearly distinct from the current skill's purpose and cannot be addressed by improving the current skill.

4. **skip** - The skill is working well enough, or the evidence is too weak or ambiguous to justify changes. No action needed.

## Editing principles (for improve_skill)

- Treat the CURRENT skill as the source of truth, not as a rough draft to be rewritten.
- Read the original skill first, then the session evidence.
- Default to targeted edits, not rewrites.
- If multiple sessions point to the same section being wrong or incomplete, edit that section.
- If failures are only corner cases, add the missing checks or clarify constraints without changing unrelated sections.
- Preserve the original structure, heading order, terminology, and effective guidance, especially parts supported by successful sessions.
- Only rewrite an entire section if the evidence shows that section is materially wrong.
- If the skill contains concrete API details (endpoints, ports, payload schemas, tool names) that are factually correct, KEEP them even if the agent did not use them well. These details are the skill's core value.

## Hard constraints

- Do NOT casually change task API contracts, ports, endpoints, output paths, payload formats, or required filenames. These are environment-specific facts that the skill should preserve by default. EXCEPTION: if the session evidence clearly shows that an API endpoint, port, or contract has changed, update the skill to reflect the corrected value.
- Do NOT remove core capabilities, API references, command patterns, or tool-usage examples unrelated to the observed failures.
- Do NOT turn the skill into a different skill with a different purpose.
- Do NOT rewrite the whole skill from scratch.
- Do NOT impose a new template, new mandatory section structure, or a different writing style unless the evidence requires it.
- Do NOT add generic best-practice guidance (for example rate-limit handling, retry logic, state management, or caching) that the agent should handle on its own. Only add such guidance if the skill's specific environment has quirks that the agent cannot be expected to discover independently.

## Conservative editing mode

- Prefer preserving existing section headings and ordering.
- If a successful session supports a section, leave that section untouched unless failure evidence explicitly contradicts it.
- Prefer tightening or clarifying an existing section over adding a brand-new section.
- Do not introduce a new large section unless failure evidence is strong and the existing structure cannot express the fix.
- If you add a new checklist item, keep it short and tied to the observed failure.

## Distinguishing skill problems from agent problems

Not every failure is a skill deficiency. Before editing, consider whether the failure was caused by:
- **The skill** (wrong, missing, or misleading guidance) -> edit the skill.
- **The agent** (subagent misuse, unnecessary restarts, context overflow, or not reading the skill properly) -> these are agent-level issues; do NOT bloat the skill with agent-runtime advice.
- **The environment** (mock API instability, network flakiness, docker quirks) -> if sessions show repeated API failures or timeouts, add a brief note about the instability so the agent knows to expect it. Keep it short; do NOT turn the skill into a retry tutorial.

Critical anti-pattern to avoid: if the skill ALREADY contains correct environment information (API endpoints, ports, payload formats, tool names) and the agent failed because it did NOT use that information, that is an AGENT problem, not a skill problem. Do NOT delete the correct API information from the skill and replace it with instructions like "go read utils.py" or "inspect the mock service code". The whole point of the skill is to save the agent from having to discover those details.

When in doubt, prefer **skip** over a speculative edit.

## Skill-writing principles (for create_skill)

- The new skill must serve a DIFFERENT purpose than ``{skill_name}``.
- Prefer a short, action-oriented name (lowercase-hyphenated slug).
- The name MUST differ from all existing skill names listed below.
- A skill should compress environment information (API endpoints, ports, payload formats, tool-specific quirks, or domain procedures), not generic best practices the agent already knows.
- Description should state what the skill does and triggering contexts, including "NOT for: ..." exclusion conditions. 2-4 sentences.
- Content should be domain-specific, practically useful, and non-obvious.
- Keep it concise, reusable, and evidence-driven.
- Write reusable guidance, not a failure summary or postmortem.

## Output format

Return EXACTLY one JSON object (no markdown fences, no extra text):

If action is improve_skill:
```
{{
  "action": "improve_skill",
  "rationale": "<why, synthesizing the evidence>",
  "skill": {{
    "name": "<keep same name>",
    "description": "<keep or improve>",
    "content": "<full updated Markdown body>",
    "category": "<keep or update>",
    "edit_summary": {{"preserved_sections": [...], "changed_sections": [...], "notes": "..."}}
  }}
}}
```

If action is optimize_description:
```
{{
  "action": "optimize_description",
  "rationale": "<why>",
  "skill": {{
    "name": "<keep same name>",
    "description": "<rewritten description with Use-when and NOT-for conditions>"
  }}
}}
```

If action is create_skill:
```
{{
  "action": "create_skill",
  "rationale": "<why a new skill is needed and why the current skill should not absorb this>",
  "skill": {{
    "name": "<new-lowercase-slug, MUST differ from {skill_name} and all existing names>",
    "description": "<2-4 sentences with triggering contexts and NOT-for conditions>",
    "content": "<skill body in Markdown>"
  }}
}}
```

If action is skip:
```
{{
  "action": "skip",
  "rationale": "<why skipping>"
}}
```
a	  You are a skill engineer for SkillClaw.

You are given summaries of agent sessions where no existing skill was referenced. These sessions may reveal patterns that could be captured as a reusable skill for future sessions.

Analyze whether these sessions reveal a common pattern, recurring challenge, or reusable strategy that would benefit future agent sessions if captured as a skill.

1. **create_skill** - A clear, teachable pattern exists that compresses environment-specific knowledge the agent cannot reliably discover on its own. Produce the new skill.
2. **skip** - No actionable or generalizable pattern. The sessions are too diverse, too domain-specific, or the issues are not solvable by skills.

## Skill-writing principles (for create_skill)

- A skill should compress environment information (API endpoints, ports, payload formats, tool-specific quirks, or domain procedures), not generic best practices the agent already knows.
- Prefer a short, action-oriented name (lowercase-hyphenated slug).
- Description should state what the skill does and triggering contexts, including "NOT for: ..." exclusion conditions. 2-4 sentences.
- Content should be domain-specific, practically useful, and non-obvious.
- Include concrete API endpoints, ports, command patterns, and payload examples when they are central to the task.
- Keep it concise, reusable, and evidence-driven.
- Write reusable guidance, not a failure summary or postmortem.
- Use imperative instructions. Organize naturally for the task.
- Do NOT add generic agent-runtime advice (rate-limit handling, retry logic, caching strategies, or state management) unless the environment has specific quirks that require it.

## When to skip

Prefer skip when:
- The failures are caused by agent-level issues (retries, context overflow, or subagent misuse) rather than missing knowledge.
- The sessions are too diverse to extract a single coherent skill.
- The pattern is something the agent should handle via general intelligence.

## Output format

Return EXACTLY one JSON object (no markdown fences, no extra text):

If action is create_skill:
```
{{
  "action": "create_skill",
  "rationale": "<why creating this skill>",
  "skill": {{
    "name": "<lowercase-hyphenated-slug>",
    "description": "<2-4 sentences with triggering contexts and NOT-for>",
    "content": "<skill body in Markdown>"
  }}
}}
```

If action is skip:
```
{{
  "action": "skip",
  "rationale": "<why skipping>"
}}
```
 c                >    t        | xs d      j                         ay)zCSet the debug dump directory used by session-level evolution calls.r
   N)strstrip_EVOLVE_DEBUG_DIR)paths    ;/root/.hermes/SkillClaw/evolve_server/pipeline/execution.pyset_evolve_debug_dirr      s     DJB--/    c                     t         S N)r    r   r   _get_evolve_debug_dirr     s    r   c                  K   d|j                  dd       d|j                  dd       d|j                  dd       d	|j                  d
d       d|j                  dd       d|j                  dd       d|j                  dd       d	|j                  d
d       d|j                  dd       d}dt        dd|dg}| j                  |dd       d{   }t        |      S 7 w)z?Merge two versions of the same skill into one superior version.z,## Version A (currently in shared storage, v_version?z	)

Name: namer
   
Description: description
Category: categorygeneral

Content:
```
contentz/
```

---

## Version B (newly evolved)

Name: z
```systemroler!   user    g333333?
max_tokenstemperatureN)get_MERGE_SKILL_SYSTEMchatr	   )llmexisting_skillincoming_skilluser_msgmessagesraws         r   execute_merger3   	  s4     7~7I7I*VY7Z6[ \##FB/0 1&**="=> ?#''
I>? @(,,Y;< =  ##FB/0 1&**="=> ?#''
I>? @(,,Y;<E
	C  &9:H-H dD
DCc"" Es   CC(C&C(c                    d| j                  dd       d| j                  dd       d| j                  dd       d	| j                  d
d       d	S )Nz## Current skill

Name: r   r
   r   r   r   r   r   r    r!   z
```

)r*   )skills    r   _build_skill_blockr6   $  sf    62&' (		-45 6YYz956 7))Ir239		>r   c                z   g }| d| D ]  }|j                  dd      }|j                  d      }|d| nd}|j                  dd      }|rd	nd}|j                  d
      xs
 t               }	|	rdt        |	       nd}
|j                  d      xs i }d}|rg }|j                  dd      }|j                  d      }|j                  dd      }|j                  dd      }|j                  dd      }|r|j                  | d       ||j                  d|d       |s|r|j                  d| d|        |r|j                  d|        |rddj	                  |       }|j                  dd      }|j                  dd      }d| | | | |
 g}|r|j                  d|        |r|j                  d|        |s|s|j                  d       |j                  d j	                  |              t        |       |kD  r!|j                  d!t        |       |z
   d"       d#j	                  |      S )$z?Format session evidence (trajectory + summary) for LLM prompts.N
session_idr   _avg_prmz, avg PRM: r
   _has_tool_errorsFz, has tool errors_skills_referencedz
, skills: 	aggregaterollout_countr   
mean_score	stabilitysuccess_count
fail_countz	 rolloutsz	mean ORM=z.3fzsuccess=z fail=z
stability=, _trajectory_summaryz### Session z**Trajectory**:
z**Analysis**:
z	(no data)z

z	
... and z more sessionsz

---

)r*   setsortedappendjoinlen)sessionsmax_sessionsblockssessionr8   avg_prmprm_str
has_errorserr_strskills	skill_strr<   aggregate_strpartsr=   r>   r?   r@   rA   
trajectorysummarys                        r   _build_session_evidencerX   .  sS   FM\* '*[[s3
++j)-4-@Ky)b[[!3U;
)3%12;ce5;j 01	KK,2	!E%MM/1=M"|4J!k26I%MM/1=M"|Q7Ji89%yC(89:
xfZLIJz)56"$TYYu%5$6 7[[3
++j"-
|G9]OG9YKXYLL,ZL9:LL?7)45'LL%fkk%()O'*R 8}|#
3x=<#?"@OPf%%r   c                "   t               }|sy t        |      }|j                  dd       ||  dz  j                  |d       ||  dz  j                  |d       |||  dz  j                  |d       t        j                  d| |       y )	NT)parentsexist_okz_system.txtzutf-8)encodingz	_user.txtz_raw_output.txtz+[DebugDump] wrote %s prompt artifacts to %s)r   r   mkdir
write_textloggerinfo)stemr"   r0   r2   	debug_dirdump_dirs         r   _write_debug_dumprd   `  s    %'IIHNN4$N/4&$$00'0J4&	""..x'.J
	tfO,	,88w8O
KK=tXNr   c           	       K   t         j                  d|      }|rt        |      nd}t        |      }| dt	        |       d| ddj                  |      xs d d}|j                  d	d
      }	t        |	||       d|dd|dg}
| j                  |
dd       d{   }t        |	|||       t        ||      S 7 w)zCCombined decision + execution for one existing-skill session group.z{skill_name}r
   ## Session evidence ( sessions)

*

## Existing skill names in the library

rB   (none)
/_r"   r#   r%   r&   皙?r'   N)	_EVOLVE_FROM_SESSIONS_SYSTEMreplacer6   rX   rI   rH   rd   r,   _parse_evolve_result)r-   
skill_namerJ   current_skillexisting_skill_namesr"   skill_sectionevidencer0   ra   r1   r2   s               r   evolve_skill_from_sessionsrv   n  s      *11.*MF9F&}5BM&x0H/
Hn* 599)*6h
7r		;  c3'DdFH- f-H-H dD
DCdFHc2Z00 Es   BB>B<B>c                *  K   t        |      }dt        |       d| ddj                  |      xs d d}d}t        |t        |       dt        d	d
|d	g}| j                  |dd       d{   }t        |t        ||       t        |d      S 7 "w)z>Combined decision + execution for the no-skill session bucket.rf   rg   rh   rB   ri   rj   no_skillr"   r#   r%   r&   rm   r'   Nr
   )rX   rI   rH   rd   _CREATE_FROM_SESSIONS_SYSTEMr,   rp   )r-   rJ   rs   ru   r0   ra   r1   r2   s           r   create_skill_from_sessionsrz     s      'x0H
Hn* 599)*6h
7r	;  Dd8(C &BCH-H dD
DCd8(CHR(( Es   A,B.B/#Bc                x   ddl }ddl}|j                  dd| j                               j                         j	                  d      }	 |j                  |      }t        |t              sy|j                  dt        j                         }|t        j                   k(  r#t        j                   |j                  dd      dS |j                  d      }	t        |	t              st        j                  d||       y|t        j"                  k(  rW|	j                  d      st        j                  d|       y|	d   |k(  r?t        j                  d|       t        j$                  }n|r|	j                  d      s||	d<   ||j                  dd      |	dS # |j                  t        f$ r |j                  d      }|j                  d      }|dk(  s||k  rt        j                  d	|       Y y	 |j                  |||d
z          }n2# |j                  t        f$ r t        j                  d|       Y Y yw xY wY w xY w)z8Parse the combined decision+execution JSON from the LLM.r   Nz```(?:json)?\s*r
   `{}z+[SessionExec] no JSON object found for '%s'   z4[SessionExec] failed to parse evolve result for '%s'action	rationale)r   r   r5   z4[SessionExec] action '%s' but no skill data for '%s'r   z?[SessionExec] create_skill action but no name provided for '%s'zH[SessionExec] create_skill returned same name '%s' - treating as improve)r   r   r5   )jsonresubr   rstriploadsJSONDecodeError
ValueErrorfindrfindr_   warning
isinstancedictr*   r   SKIPCREATEIMPROVE)
r2   rq   r   r   cleanresultstartendr   
skill_datas
             r   rp   rp     s   FF%r399;7==?FFsKEE" fd#ZZ."5"56F$$$(--FJJ{TV<WXXG$Jj$'MvWab&&&~~f%NN\^hif+NNZ $++F	JNN62'
6 ZZR0 K   *- 


3kk#B;#,NNH*U	ZZecAg 67F$$j1 	NNQS]^	 
s7   F AH9+HH9+H2.H91H22H98H9)r   r   returnNone)r   r   )r-   r   r.   r   r/   r   r   Optional[dict])r5   r   r   r   )   )rJ   
list[dict]rK   intr   r   r   )
ra   r   r"   r   r0   r   r2   z
str | Noner   r   )r-   r   rq   r   rJ   r   rr   r   rs   	list[str]r   r   )r-   r   rJ   r   rs   r   r   r   )r2   r   rq   r   r   r   )__doc__
__future__r   loggingpathlibr   typingr   core.constantsr   core.llm_clientr   
core.utilsr	   	getLogger__name__r_   r+   rn   ry   r   r   r   r3   r6   rX   rd   rv   rz   rp   r   r   r   <module>r      s  
 #    + , +			8	$ BE  N9  v  0#	## # 	#6/&dO1	11 1 "	1
 $1 1>)	)) $) 	)42r   