
    *"hj                         d Z ddlm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
 ddlmZ  ej                  e      Z ej                   dej"                        Zd	Zd
ZdZdZdZddZddZddZddZddZddZddd	 	 	 	 	 	 	 	 	 	 	 	 	 ddZy)ab  
Optional post-generation verifier for workflow-evolved skills.

When enabled, this verifier runs after a candidate skill is generated but
before it is uploaded to shared storage. It is intentionally conservative:
if the verifier cannot confidently approve the candidate, the upload is
blocked and the rejection reason is recorded in the evolve summary.
    )annotationsN)AnyOptional   )DecisionAction)AsyncLLMClientz\{.*\}   i  i@  i  au  You are the final publication gate for SkillClaw workflow evolution.

You are given:
- the proposed action
- the candidate skill
- optional current skill content
- summarized evidence from the sessions that motivated the change

Your job is NOT to improve the skill. Your job is only to decide whether this
candidate is safe and worthwhile to publish to the shared skill store.

Approve the candidate only if ALL of the following are true:
- it is grounded in the provided evidence
- it does not throw away useful existing environment-specific facts without evidence
- it is specific and reusable rather than generic agent advice
- it is coherent enough to be shared with other users immediately

Reject the candidate if ANY of the following are true:
- it is speculative or weakly supported by the evidence
- it removes useful existing instructions, endpoints, ports, filenames, or payload details without justification
- it mostly adds generic best practices instead of environment-specific knowledge
- it should stay as a local draft or needs more evidence before publication

For `optimize_description`, verify only whether the new description is a safer
and more accurate trigger than the old one.

For `create_skill`, verify that the new skill is genuinely distinct and
generalizable from the provided sessions.

Output EXACTLY one JSON object with:
- "decision": "accept" or "reject"
- "score": number in [0, 1]
- "reason": short explanation
- "checks": object with numeric scores in [0, 1] for:
  - "grounded_in_evidence"
  - "preserves_existing_value"
  - "specificity_and_reusability"
  - "safe_to_publish"

No markdown fences. No extra text.
c                l    t        | xs d      j                         }t        |      |k  r|S |d | dz   S )N z...)strstriplen)value	max_charstexts      @/root/.hermes/SkillClaw/evolve_server/pipeline/skill_verifier.py
_clip_textr   H   s<    u{!!#D
4yI
e##    c                   t        j                  ddt        | xs d            j                         j	                  d      }|sy 	 t        j                  |      }t        |t              r|S 	 t        j                  |      }|sy 	 t        j                  |j                  d            }t        |t              r|S d S # t
        j                  t        f$ r Y lw xY w# t
        j                  t        f$ r Y y w xY w)Nz```(?:json)?\s*r   `r   )resubr   r   rstripjsonloads
isinstancedictJSONDecodeError
ValueError_JSON_BLOCK_REsearchgroup)r   cleanobjmatchs       r   _extract_json_objectr&   O   s    FF%r3tzr?;AACJJ3OEjjc4 J !
 !!%(EjjQ( S$'31T1   *-    *- s$   &B? $C ?CCC:9C:c           	         t        | t        t        f      rt        | t              ry t	        dt        dt        |                   }t        |d      S )Ng        g      ?   )r   intfloatboolmaxminround)r   scores     r   _normalize_scorer0   d   s?    ec5\*j.ESeEl+,E?r   c                    t        | t              si S i }dD ]$  }t        | j                  |            }| |||<   & |S )N)grounded_in_evidencepreserves_existing_valuespecificity_and_reusabilitysafe_to_publish)r   r   r0   get)
raw_checksoutkeyr/   s       r   _normalize_checksr:   k   sR    j$'	C  !!45CH Jr   c                    t        |       }||S |sy t        t        |j                               t	        |      z  d      S )Nr(   )r0   r.   sumvaluesr   )	raw_scorechecksr/   s      r   _compute_scorer@   {   s>    Y'EV]]_%F3Q77r   c                   g }| d t          D ]  }t        |j                  dd            t        |j                  dd      t              d}|j                  d      }|rt        d |D              |d<   |j                  d      }t        |t              r!t        |j                  d	            }|||d
<   t        |j                  d            }|||d<   |j                  |        |S )N
session_idr   _summary)rB   summary_skills_referencedc              3  Z   K   | ]#  }t        |xs d       st        |xs d        % yw)r   N)r   ).0ss     r   	<genexpr>z*_build_session_evidence.<locals>.<genexpr>   s%     .\sSTSZXZ|s17|.\s   ++skills_referenced_judge_scoresoverall_scorejudge_overall_score_avg_prmavg_prm)
_MAX_SESSIONSr   r6   r   _SUMMARY_MAX_CHARSsortedr   r   r0   append)sessionsevidencesessionitemskillsjudge_scoresoverallrO   s           r   _build_session_evidencer[      s    %'HN]+ gkk,;<!'++j""=?QR 
 12(..\V.\(\D$%{{?3lD)&|'7'7'HIG".5*+"7;;z#:;%DO!" Or   g      ?)current_skill	min_scorec          
     x  K   |t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd      t              ddt	        |      t        t        |      d	      |t        j                  k(  |t        j                  k(  d
d}|rst        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd      t              d|d<   	 | j                  dt        ddt        j                  |dd      dgdd       d{   }t%        |      }	|	sCt         j#                  d|j                  dd             ddddt        t        |      d	      di dS t'        |	j                  d            }
t)        |	j                  d      |
      }t        |	j                  dd      xs d      j+                         j-                         }t        |	j                  d       xs( |	j                  d!      xs |	j                  d"      xs d      j+                         }|d#k(  }||t        |      k  rd}|d$vr|duxr |t        |      k\  }dt/        |      |rd#nd|t        t        |      d	      ||
dS 7 p# t        $ rQ}t         j#                  d|j                  dd      |       ddddt        t        |      d	      d| i dcY d}~S d}~ww xY ww)%z@Verify a candidate skill before publishing it to shared storage.namer   descriptioncategorygeneralcontent)r_   r`   ra   rc   Nr(   )optimize_description_onlycreate_skill)actioncandidate_skillr\   session_evidenceacceptance_thresholdnotesr\   system)rolerc   userFr   )ensure_asciiindenti  g?)
max_tokenstemperaturez1[SkillVerifier] verifier call failed for '%s': %sTrejectzVerifier call failed: )enabledaccepteddecisionr/   	thresholdreasonr?   z0[SkillVerifier] invalid verifier output for '%s'zVerifier returned invalid JSON.r?   r/   ru   rw   	rationalerj   accept>   ry   rr   )r   r6   r   _SKILL_CONTENT_MAX_CHARSr[   r.   r*   r   OPTIMIZE_DESCCREATE_CURRENT_SKILL_MAX_CHARSchat_VERIFY_SKILL_SYSTEMr   dumps	Exceptionloggerwarningr&   r:   r@   r   lowerr+   )llmskillrT   action_typer\   r]   payloadrawexcparsedr?   r/   decision_rawrw   rt   s                  r   verify_skill_candidater      s     		&"-.uyy;<EIIj)<=!%))Ir":<TU	
 3H= %eI&6 :)48T8T)T'>+@+@@
G  ))&"56}00CDM--j)DE!-"3"3Ir"BD\]	$
 
HH!.BCDJJwU[\,]^   
 
( "#&FI599U[]_K`a uY/37
 	
 vzz(34F6::g.7Evzz*b17R8>>@FFHLH%]K)@]FJJwDW][]^ddfFx'HUU9%55//$B%	2B)B N (Hh5+Q/ Y
  

JEIIV\^`Lacfg uY/3.se4
 	


sJ   D.L:19K *K+K /E+L:K 	L7&AL2,L7-L:2L77L:)r   r   r   r)   returnr   )r   r   r   Optional[dict[str, Any]])r   r   r   Optional[float])r7   r   r   dict[str, float])r>   r   r?   r   r   r   )rT   list[dict[str, Any]]r   r   )r   r   r   dict[str, Any]rT   r   r   r   r\   r   r]   r*   r   r   )__doc__
__future__r   r   loggingr   typingr   r   core.constantsr   core.llm_clientr   	getLogger__name__r   compileDOTALLr    rP   rQ   rz   r}   r   r   r&   r0   r:   r@   r[   r    r   r   <module>r      s    #   	   + ,			8	$Iryy1   ) X$2* 88 /3W	WW #W 	W ,W W Wr   