
    i{                        d Z ddl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 ddl	m
Z
 ddlZej                  j                  d e ee      j!                         j"                               ddlmZ defdZ	 dd	ed
ede
e   defdZdedede
eeee   f      fdZd	ededee   defdZded	eddfdZ	 dd	ededede
e   de
e   f
dZd	edee   fdZddZedk(  r e        yy)uT   passive_feedback.py - 파일 변경 감지 및 피드백 학습 저장 유틸리티.    N)datetime)Path)Optional)add_learningreturnc                      t         j                  j                  d      } | rt        |       S t        t              j                         j                  j                  S )NWORKSPACE_ROOT)osenvirongetr   __file__resolveparent)vs    //home/jay/workspace/scripts/passive_feedback.py_get_workspace_rootr      s?    


'(A47CT(^335<<CCC    
skill_name	file_pathtask_idc                 b   t               }t        j                         }|j                  d      }|dz  dz  | z  dz  }|j	                  dd       || dz  }|j                  t        |      j                  d	      d	       t        |j                               | |j                         |d
S )u[   file_path 내용을 스냅샷 디렉토리에 복사하고 메타데이터를 반환한다.z%Y%m%d_%H%M%Smemoryskill-feedback	snapshotsTparentsexist_okz.txtutf-8encoding)snapshot_pathr   	timestampr   )r   r   nowstrftimemkdir
write_textr   	read_textstrr   	isoformat)r   r   r   workspace_rootr#   timestamp_strsnap_dir	snap_paths           r   save_snapshotr.      s     )*N
,,.CLL1M(+;;jH;VHNN4$N/m_D11Ii22G2DwWY..01 ]]_	 r   originalmodifiedc                    | j                  d      }|j                  d      }g }t        j                  ||d      D ]  }|j                  d      s"|j                  d      s|j                  d      r7|j                  d      r:|d	d
 j	                  d      }|j                         sm|j                  d|d       |j                  d      s|d	d
 j	                  d      }|j                         s|j                  d|d        |sy
t        d |D              }t        d |D              }||k(  ry
dj                  d |D              }	|	|fS )uf   두 텍스트를 비교하여 의미 있는 diff를 반환한다. 공백만 다른 경우 None 반환.T)keepends )linetermz---z+++z@@-   N
remove)typeline+addc              3   T   K   | ]   }|d    dk(  s|d   j                          " yw)r9   r8   r:   Nstrip.0ds     r   	<genexpr>z+_compute_meaningful_diff.<locals>.<genexpr>A   s'     \1aiS[F[QvY__.\   ((c              3   T   K   | ]   }|d    dk(  s|d   j                          " yw)r9   r<   r:   Nr>   r@   s     r   rC   z+_compute_meaningful_diff.<locals>.<genexpr>B   s'     V1V9PUCU!F)//+VrD   c              3   F   K   | ]  }|d    dk(  rdnddz   |d   z     yw)r9   r8   r5   r;    r:   N r@   s     r   rC   z+_compute_meaningful_diff.<locals>.<genexpr>E   s,     fVW&	X 53#E&	Qfs   !)	
splitlinesdifflibunified_diff
startswithrstripr?   appendsortedjoin)
r/   r0   
orig_lines	mod_lines
diff_linesr:   actualremove_strippedadd_strippedsummarys
             r   _compute_meaningful_diffrX   ,   s?   
 $$d$3J##T#2IJ$$ZRH 
C??5!T__U%;tt?T??3!"X__T*F||~!!8V"DE__S!!"X__T*F||~!!5&"AB
C \
\\OVZVVL,&iif[effGJr   diff_summaryrS   c                     t        j                         }d|  d| d}|j                  j                  ddd|dg      }|j                  d	   }t        |d
d      }t        |t              r|S t        |      S )u5   anthropic SDK로 diff에서 learning을 추출한다.u   스킬 'u8   '의 파일이 다음과 같이 변경되었습니다:

uu   

이 diff에서 어떤 개선이 이뤄졌는지 분석해줘. 한 문장으로 핵심 인사이트를 요약해줘.zclaude-sonnet-4-6i  user)rolecontent)model
max_tokensmessagesr   textN)	anthropic	Anthropicr`   creater]   getattr
isinstancer(   )r   rY   rS   clientpromptresponseblockra   s           r   _extract_learningrk   I   s       "F
:,X. ~	~ 
 %%!!f56 & H
 QE5&$'DdC(48c%j8r   recordc                     t               }|dz  dz  |z  }|j                  dd       |dz  j                  dd      5 }|j                  t	        j
                  | d	
      dz          ddd       y# 1 sw Y   yxY w)u1   passive-diffs.jsonl에 레코드를 append한다.r   r   Tr   passive-diffs.jsonlar   r   Fensure_asciir7   N)r   r%   openwritejsondumps)rl   r   r*   diff_dirfs        r   _save_diff_recordrx   _   s{    (*N(+;;jHHNN4$N/
*
*	0	0w	0	G ?1	

66=>? ? ?s   *A22A;original_pathmodified_pathc                    t        |      j                  d      }t        |      j                  d      }t        ||      }|y|\  }}t        | ||      }	t	               }
|
dz  dz  dz  }t        | d|	|      }t        j                         j                         | |t        |
dz  d	z  | z  d
z        |||	t        |j                  dd            d}t        ||        |S )uk   두 파일을 비교하여 의미 있는 diff 감지 후 learning 저장. 공백만 변경 시 None 반환.r   r   Nr   zskill-learningzlearnings.jsonlzjay-feedback)r   sourcelearninglearnings_pathr   r   idr3   )r"   r   r   r!   rY   rS   learning_extractedlearning_id)r   r'   rX   rk   r   r   r   r#   r)   r(   r   rx   )r   ry   rz   r   r/   r0   resultrY   rS   learning_textr*   r~   learning_entryrl   s                 r   detect_diffr   h   s    M",,g,>HM",,g,>H%h9F~%L*%j,
KM(*N#h.1AADUUN!%	N \\^--/ ^h69IIJVYdde$ +>--dB78	F fj)Mr   c                     t               }|dz  dz  | z  dz  }|j                         sg S |j                  d      j                         j	                         D cg c](  }|j                         st        j                  |      * c}S c c}w )u[   스킬의 passive-diffs.jsonl 히스토리를 반환한다. 파일 없으면 빈 리스트.r   r   rn   r   r   )r   existsr'   r?   rI   rt   loads)r   r*   	diff_filer:   s       r   get_historyr      s    (*N),<<zILaaI	)2)<)<g)<)N)T)T)V)a)a)ctgkgqgqgsDJJtttts   B1Bc                     t        j                  d      } | j                  dd      }|j                  d      }|j	                  dd	       |j	                  d
d	       |j	                  ddd       |j                  d      }|j	                  dd	       |j	                  dd	       |j	                  dd	       |j	                  ddd       |j                  d      }|j	                  dd	       | j                         }|j                  dk(  rNt        |j                  |j                  |j                        }t        t        j                  |dd             y|j                  dk(  rgt        |j                  |j                  |j                   |j                        }|t        d       yt        t        j                  |dd             y|j                  dk(  rYt#        |j                        }|st        d|j                   d       y|D ]"  }	t        t        j                  |	d             $ y| j%                          t'        j(                  d       y)u   CLI 진입점.u   passive-feedback 유틸리티)descriptioncommandu	   명령어)desthelpsnapshotz--skillT)requiredz--filez	--task-idr   N)r   defaultdetectz
--originalz
--modifiedhistory)r   r   r   F   )rq   indent)r   u6   의미 있는 변경 없음 (공백/포맷만 변경).'u.   ' 스킬의 diff 히스토리가 없습니다.rp   r6   )argparseArgumentParseradd_subparsers
add_parseradd_argument
parse_argsr   r.   skillfiler   printrt   ru   r   r/   r0   r   
print_helpsysexit)
parser
subparserssnap_pdet_phist_pargsrreshistrecs
             r   mainr      s   $$1PQF&&IK&HJ"":.F
	D1
40
)TB!!(+E	y40	|d3	|d3	{DA""9-F
	D1D||z!TZZ499dll[djjq9:		!$**dmmT]]DLLY;JK$**SuQ?@		"4::&Adjj\!OPQ ;djj59:; 	r   __main__)N)r   N) __doc__r   rJ   rt   r
   r   r   pathlibr   typingr   rb   pathinsertr(   r   r   r   learnings_archiverr   r   dictr.   tuplelistrX   rk   rx   r   r   r   __name__rH   r   r   <module>r      s}   Z    	 
     3tH~--/667 8 +DT D " c] 
	* eCdO$%:999 T
9 		9,?d ? ? ? "	!!! ! c]	!
 d^!HuC uDJ u$N zF r   