
    (<i                       d dl m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	 ddZ
ddZddZdd	Zdd
ZddZddZddZddZddZ	 	 	 	 	 	 	 	 	 	 ddZddZddZddZ	 	 d 	 	 	 	 	 	 	 	 	 	 	 	 	 d!dZddZddZy)"    )annotationsN)datetimetimezone)Path)Anyc                     t         j                  j                  d      } | rt        |       S t        t              j
                  j
                  S )z>WORKSPACE_ROOT env var takes priority; fallback to scripts/../WORKSPACE_ROOT)osenvirongetr   __file__parent)env_vals    N/home/jay/workspace/.worktrees/task-2057-dev2/scripts/output_review_helpers.pyget_workspace_rootr      s8    jjnn-.GG}>  '''    c                 (    t               dz  dz  dz  S )Nmemoryskill-learning	championsr    r   r   _champions_dirr      s    (*-==KKr   c                 (    t               dz  dz  dz  S )Nr   r   zchampions-archiver   r   r   r   _champions_archive_dirr      s    (*-==@SSSr   c                 (    t               dz  dz  dz  S )Nr   r   zlearnings.jsonlr   r   r   r   _learnings_pathr      s    (*-==@QQQr   c                 (    t               dz  dz  dz  S )Nskillssharedzeval-axes.jsonr   r   r   r   _eval_axes_pathr!      s    (*X58HHHr   c                    t               }|j                         sg S 	 t        j                  |j	                  d            }|j                  | g       S # t        j                  t        f$ r g cY S w xY w)zFLoad eval axes for a skill from eval-axes.json. Returns [] if missing.utf-8encoding)r!   existsjsonloads	read_textr   JSONDecodeErrorOSError)
skill_namepathdatas      r   load_eval_axesr/   #   sf    D;;=	#zz$..'.*JKxx
B''  '* 	s   6A A32A3c                    t               |  dz  }|j                         syt        j                  |j	                  d            S )z<Load champions/{skill_name}.json. Returns None if not found..jsonNr#   r$   )r   r&   r'   r(   r)   )r,   r-   s     r   load_championr2   /   s<    E22D;;=::dnngn677r   c                    t               }|j                  dd       ||  dz  }|j                  t        j                  |dd      d       |S )	zHSave data to champions/{skill_name}.json. Creates directories if needed.Tparentsexist_okr1   F   )ensure_asciiindentr#   r$   )r   mkdir
write_textr'   dumps)r,   r.   champions_dirr-   s       r   save_championr>   7   sP    "$Mt4j\//DOODJJt%BWOUKr   c                   t               |  dz  }|j                         syt        j                  t        j
                        j                  d      }t               | z  }|j                  dd       || dz  }|j                  |       |S )zwMove existing champion to champions-archive/{skill_name}/{timestamp}.json.
    Returns None if champion does not exist.r1   Nz%Y%m%dT%H%M%SZTr4   )
r   r&   r   nowr   utcstrftimer   r:   rename)r,   source	timestamparchive_skill_dirdests        r   archive_championrH   @   s     :,e 44F==?X\\*334DEI.0:=D48)E22D
MM$Kr   c                    t               }|j                  j                  dd       |j                  dd      5 }|j	                  t        j                  | d      dz          d	d	d	       y	# 1 sw Y   y	xY w)
zEAppend a JSON line to learnings.jsonl. Creates directories if needed.Tr4   ar#   r$   F)r8   
N)r   r   r:   openwriter'   r<   )entryr-   fs      r   append_learningrP   N   sd    DKKdT2	3	) >Q	

5u5<=> > >s   *A..A7c                    	 ddl m}  || |||      S # t        t        f$ r1 t	        |       t	        |      }}||k\  rdnd}|d| d| d| i dcY S w xY w)	uH   AI 비교 판정. ANTHROPIC_API_KEY가 없으면 길이 기반 fallback.r   )compare_outputs_aiABzFallback comparison for 'z	': A len=z, B len=)winnerreasonscores)output_review_airR   ImportErrorEnvironmentErrorlen)output_aoutput_b	eval_axesr,   rR   len_alen_brU   s           r   compare_outputsra   V   sv    
7!(HiLL)* 
8}c(muC1*YugXV[U\]
 	
	
s    =AAc                :   t        t        j                  j                  dd            dz  dz  dz  dz  }|j	                         sy	 t        j                  |j                  d	            }|j                  |       S # t
        j                  t        f$ r Y yw xY w)
u;   skill-registry.json에서 스킬 정보를 로드합니다.HOME z.clauder   r    zskill-registry.jsonNr#   r$   )
r   r
   r   r   r&   r'   r(   r)   r*   r+   )r,   registry_pathr.   s      r   load_skill_registryrf   l   s    34y@8KhVYnnM!zz-1171CDxx
##  '* s   5A> >BBc           	         ddl }|j                  dg       D ]P  }	 |j                  j                  dt	        t        t              j                               ddlm	}  || d|       R y# t        t        f$ r Y ew xY w)uL   enhancement에서 learnings를 learnings_archiver를 통해 저장합니다.r   N	learnings)add_learningzchampion-battle)r,   rD   learning)sysr   r-   insertstrr   r   r   learnings_archiverri   rY   	Exception)r,   enhancementrk   learning_textarchiver_adds        r   save_enhancement_learningsrs   x   so    $b9 	HHOOAs4>#8#89:GJ7HS`a Y' 		s   AA++A=<A=c                    | j                  dd      }| j                  dd      }| j                  dd      }|dk\  rd| d<   | S |dk\  rd	| d<   | S |d
k\  rd| d<   | S d| d<   | S )zCUpdate status based on win/loss record. Priority order as per spec.reinit_count_this_monthr   consecutive_lossesconsecutive_defensesr7   manual_intervention_requiredstatus   unstable   stableactiver   )championreinitlossesdefensess       r   update_champion_statusr      s    \\3Q7F\\.2F||2A6H{; O 
1' O 
Q% O &Or   c                   t        j                  t        j                        j	                         }t        j                  t        j                        }|j
                  dk(  r"|j                  |j                  dz   dd      }n |j                  |j
                  dz   d      }|j                  d      }	| |||||dddd|	||dS )	z,Build a champion.json schema-compliant dict.      )yearmonthday)r   r   z%Y-%m-%dr~   r   )r,   
skill_typechampion_outputeval_axes_used
created_at	last_usedry   rw   rv   ru   month_reset_dateinit_methodbenchmark_source)	r   r@   r   rA   	isoformatr   replacer   rB   )
r,   r   r   r   r   r   r@   today
next_monthr   s
             r   build_champion_datar      s     ,,x||
$
.
.
0C LL&E{{b]]

QaQ]G
]]qa]@
!**:6 ! *( !#$,", r   c                @    | j                  dd      dz   | d<   d| d<   | S )zKRecord a defense: increment consecutive_defenses, reset consecutive_losses.rw   r   r   rv   r   r   s    r   record_defenser      s/    '/||4JA'NQR'RH#$%&H!"Or   c                @    | j                  dd      dz   | d<   d| d<   | S )zHRecord a loss: increment consecutive_losses, reset consecutive_defenses.rv   r   r   rw   r   r   s    r   record_lossr      s.    %-\\2F%JQ%NH!"'(H#$Or   )returnr   )r,   rm   r   	list[str])r,   rm   r   zdict[str, Any] | None)r,   rm   r.   dict[str, Any]r   r   )r,   rm   r   zPath | None)rN   r   r   None)
r\   rm   r]   rm   r^   r   r,   rm   r   r   )r,   rm   rp   r   r   r   )r   r   r   r   )full_benchmarkonline_expert)r,   rm   r   rm   r   rm   r   r   r   rm   r   rm   r   r   )
__future__r   r'   r
   r   r   pathlibr   typingr   r   r   r   r   r!   r/   r2   r>   rH   rP   ra   rf   rs   r   r   r   r   r   r   r   <module>r      s    "  	 '  (LTRI	8>


 
 	

 
,	. (+!!! ! 	!
 ! ! !Hr   