
    i2                     x   d 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
mZ  ee      Z eej"                  j%                  dd            Zed	z  d
z  Zed	z  dz  Zed	z  dz  Z eej"                  j%                  d e ej0                         dz  dz  dz  d	z                    Zed
z  Zdedee   fdZdedee   fdZdededee   fdZdedefdZ	 	 	 d!dddedededz  dedz  dedz  de de!fdZ"	 	 d"dedz  dedz  dee!   fd Z#y# e$ r ddlZ ej                   e      ZY w xY w)#u   
Memory Check Confirmation Number System (MC)

매 task 위임 시 MC-XXXX를 발급하여 메모리 읽기 여부를 추적한다.
MEMORY.md의 ★ 항목과 관련 피드백 파일 목록을 로그에 기록한다.
    N)datetime)Path)Any)
get_loggerWORKSPACE_ROOTz/home/jay/workspacememoryz	MEMORY.mdzmemory-check-log.jsonztask-timers.jsonMEMORY_CHECK_FEEDBACK_DIRz.claudeprojectsz%-home-jay--cokacdir-workspace-autosetmemory_pathreturnc                    	 | j                         sg S | j                  d      }g }	 |j                  d      D ]!  }d|vr	|j                         }t        j                  dd	|      }t        j                  d
d|      }t        j                  dd|      }t        j                  dd|      }t        j                  dd|      }t        j                  dd|      }t        j                  dd|      }t        j                  dd	|      }t        j                  dd	|      }t        j                  dd|      j                         }|s|j                  |       $ 	 |S # t        $ r'}t        j	                  d|  d|        g cY d}~S d}~ww xY w# t        $ r'}t        j	                  d|  d|        g cY d}~S d}~ww xY w)u$  memory_path 파일에서 ★ 포함 라인을 추출하고 마크다운 서식을 제거한다.

    Args:
        memory_path: 읽을 MEMORY.md 파일 경로

    Returns:
        ★ 항목 문자열 리스트 (마크다운 서식 제거됨). 파일 없거나 에러 시 빈 리스트.
    utf-8encodingu)   [parse_star_items] 파일 읽기 실패 (): N
u   ★z
^#{1,6}\s* z\*{1,3}([^*]*)\*{1,3}z\1z_{1,3}([^_]*)_{1,3}z~~([^~]*)~~z	`([^`]*)`z\[([^\]]*)\]\([^)]*\)z!\[([^\]]*)\]\([^)]*\)z	^[-*+]\s+z	^\d+\.\s+z\s+ u&   [parse_star_items] 파싱 중 에러 ()
exists	read_text	Exceptionloggerdebugsplitstripresubappend)r   contenteresultslinecleaneds         C/home/jay/workspace/.worktrees/task-2116-dev1/utils/memory_check.pyparse_star_itemsr%   )   s   !!#I'''9
 GMM$' 	(DD jjlGff]B8Gff5ugFGff3UGDGff^UG<Gff\5':Gff5ugFGff6wGGff\2w7Gff\2w7GffVS'288:Gw'3	(< NI  @SQRPSTU	@  =k]#aSQR	sF   E" E" D F F "	F+FFF	GG :G Gfeedback_dirc                     	 | j                         sg S t        d | j                  d      D              S # t        $ r'}t        j                  d|  d|        g cY d}~S d}~ww xY w)u$  feedback_dir에서 feedback_*.md 패턴에 맞는 파일명 리스트를 반환한다.

    Args:
        feedback_dir: 피드백 파일이 있는 디렉토리 경로

    Returns:
        파일명 리스트 (경로 없이 파일명만). 디렉토리 없거나 에러 시 빈 리스트.
    c              3   4   K   | ]  }|j                     y w)N)name).0ps     r$   	<genexpr>z&find_feedback_files.<locals>.<genexpr>i   s     IaffIs   zfeedback_*.mdu2   [find_feedback_files] 디렉토리 읽기 실패 (r   N)r   sortedglobr   r   r   )r&   r    s     r$   find_feedback_filesr/   ]   sf    ""$IIl&7&7&HIII I,WZ[\Z]^_	s   5  5 	A%A A% A%	task_descc           	      D   	 t        |      }|sg S | j                         g }|D ]  }|}|j                  d      r|t        d      d }|j	                  d      r|dd }|j                  d      }|D cg c]-  }|st        j                  d|t        j                        r,|/ }}|st        fd|D              }	t        |      dk  rdnd	}
|	|
k\  s|j                  |        |S c c}w # t        $ r$}t        j                  d
|        g cY d}~S d}~ww xY w)u  task_desc 내용에 키워드 매칭되는 피드백 파일 목록을 반환한다.

    파일명에서 키워드를 추출하여 task_desc와 2개 이상 매칭 시 포함.
    키워드가 1개인 짧은 파일명은 1개 매칭으로도 포함.

    Args:
        task_desc: 작업 설명 문자열
        feedback_dir: 피드백 파일 디렉토리 경로

    Returns:
        매칭된 피드백 파일명 리스트
    	feedback_Nz.md_z^v?\d+$c              3   ,   K   | ]  }|v sd   yw)   N )r*   kw
task_lowers     r$   r,   z)match_feedback_to_task.<locals>.<genexpr>   s     GBbJ6FaGs   	r6      u,   [match_feedback_to_task] 매칭 중 에러: )r/   lower
startswithlenendswithr   r   match
IGNORECASEsumr   r   r   r   )r0   r&   feedback_filesmatchedfnamestempartsr+   keywordsmatch_count	thresholdr    r9   s               @r$   match_feedback_to_taskrJ   o   s#   ",\:I__&
# 	&ED{+C,./}}U#CRy JJsOE#(]aAbhhz1bmm6\]H] G(GGK !]a/QIi'u%+	&.  ^  CA3GH	sG   C2 A#C2 5C-=%C-#C-'0C2 C2 -C2 2	D;DDDlog_pathc                    	 | j                         syt        | dd      5 }t        j                  |      }ddd       j	                  dg       }|sy|d   j	                  dd	      }t        j                  d
|      }|syt        |j                  d            dz   }|dk  rd|dS d| S # 1 sw Y   yxY w# t        $ r"}t        j                  d|        Y d}~yd}~ww xY w)uI  log_path의 JSON 파일에서 다음 MC ID를 계산하여 반환한다.

    checks 배열의 마지막 mc_id에서 숫자를 추출해 +1 한다.

    Args:
        log_path: memory-check-log.json 파일 경로

    Returns:
        "MC-XXXX" 형식의 ID 문자열 (제로패딩 4자리, 9999 초과 시 그대로 증가)
    zMC-0001rr   r   Nchecksmc_idzMC-0000zMC-(\d+)r6   i'  zMC-04du&   [get_next_mc_id] MC ID 계산 실패: )r   openjsonloadgetr   searchintgroupr   r   r   )rK   fdatarN   
last_mc_idr?   next_numr    s           r$   get_next_mc_idr]      s     (C'2 	 a99Q<D	  (B'BZ^^GY7
		+z2u{{1~&*t#''
###	  	 $  =aSABsD   B; B; B/B; -B; 'B; *B; /B84B; ;	C&C!!C&F)_skip_anu_memorytask_idr^   c                   |du}|t         }|t        }|t        }|j                  dz  }d}	 |j                  j	                  dd       t        |d      }t        j                  |t        j                         t        |      }	g }
|s%|s#t        j                         rt        t              }
t               }g }|	|
z   D ])  }||vs|j                  |       |j                  |       + t        ||      }t!        |      }t#        j$                         j'                         }|j                         r.	 t        |dd      5 }t)        j*                  |      }ddd       nd	g i}d	vrg |d	<   ||z   }|| |t1        |      |d
}|r||d<   |d	   j                  |       t        |dd      5 }t)        j2                  ||dd       ddd       t4        j7                  d| d|  dt1        |       dt1        |       d	       || |t1        |      |d
|6	 t        j                  |t        j8                         |j;                          S S # 1 sw Y   xY w# t(        j,                  t.        f$ r d	g i}Y w xY w# 1 sw Y   xY w# t<        $ r Y S w xY w# t<        $ rk}t4        j?                  d|        i cY d}~|E	 t        j                  |t        j8                         |j;                          S # t<        $ r Y S w xY wS d}~ww xY w# |E	 t        j                  |t        j8                         |j;                          w # t<        $ r Y w w xY ww xY w)u  MC(Memory Check Confirmation Number)를 발급하고 로그에 기록한다.

    워크스페이스 MEMORY.md와 Anu MEMORY.md에서 ★ 항목을 파싱하고,
    관련 피드백 파일을 매칭하여 로그에 기록한다.

    Args:
        task_id: 태스크 ID (예: "task-1454.1")
        task_desc: 작업 설명
        log_path: 로그 파일 경로 (기본: _DEFAULT_LOG_PATH)
        memory_path: 워크스페이스 MEMORY.md 경로 (기본: _DEFAULT_MEMORY_PATH)
        feedback_dir: 피드백 파일 디렉토리 (기본: _ANU_MEMORY_DIR)

    Returns:
        {"mc_id": "MC-XXXX", "task_id": "...", "timestamp": "...",
         "star_items_checked": N, "memory_items_read": [...]}
        에러 시 빈 dict 반환
    Nz.memory-check-log.lockT)parentsexist_okwrM   r   r   rN   )rP   r_   	timestampstar_items_checkedmemory_items_readmatched_feedback_filesFr:   )ensure_asciiindentz[issue_mc] u    발급: task_id=u   , ★항목=u   개, 피드백=u   개u&   [issue_mc] MC 발급 실패 (무시): ) _DEFAULT_LOG_PATH_DEFAULT_MEMORY_PATH_ANU_MEMORY_DIRparentmkdirrR   fcntlflockLOCK_EXr%   _ANU_MEMORY_PATHr   setaddr   rJ   r]   r   now	isoformatrS   rT   JSONDecodeErrorOSErrorr=   dumpr   r   LOCK_UNcloser   warning)r_   r0   rK   r   r&   r^   _custom_memory	lock_pathlock_fdws_star_itemsanu_star_itemsseenall_star_itemsitemmatched_feedbackrP   rd   rY   log_datarf   entryr    s                         r$   issue_mcr      sm   4 !,N$*&"::IGSdT:y#&GU]]+ )5 %'&6;K;R;R;T-.>?N $&!N2 	,D4%%d+	, 2)\J x( LLN,,.	??*(C': ,a#yy|H,
 !"~H8#!#HX*-== ""%n"5!2!
 .>E*+!!%((C'2 	AaIIha@	A 	% 1' ;^,- .-./s4	
 ""%n"5!2
 GU]]3 [, ,(('2 *$b>*,	A 	A2    ?sCD	GU]]3 	 	 GU]]3 	 s   BJ 	A-J 7I II #AJ 0I?
AJ 4JII I<8J ;I<<J ?JJ 	JJ	L#L	<L=L 4K99	LL	LL M4M
	M
	MMMMtimers_pathc                    | t         } |t        }	 g }|j                         rt        |dd      5 }t	        j
                  |      }ddd       j                  di       j                         D ]>  \  }}|j                  d      dk(  s|j                  ||j                  dd	      d
       @ |sg S t               }| j                         rj	 t        | dd      5 }t	        j
                  |      }ddd       j                  dg       D ]'  }	|	j                  d      }
|
s|j                  |
       ) 	 |D cg c]  }|d   |vs| c}S # 1 sw Y   xY w# 1 sw Y   kxY w# t        j                  t        f$ r"}t        j                  d|        Y d}~gd}~ww xY wc c}w # t        $ r$}t        j                  d|        g cY d}~S d}~ww xY w)ur  running 상태이지만 MC가 발급되지 않은 태스크 목록을 반환한다.

    Args:
        log_path: memory-check-log.json 경로 (기본: _DEFAULT_LOG_PATH)
        timers_path: task-timers.json 경로 (기본: _DEFAULT_TIMERS_PATH)

    Returns:
        [{"task_id": "task-1454.1", "team_id": "dev1-team"}, ...]
        에러 시 빈 리스트 반환
    NrM   r   r   tasksstatusrunningteam_idr   )r_   r   rN   r_   u3   [get_unchecked_tasks] 로그 파일 읽기 실패: u%   [get_unchecked_tasks] 조회 실패: )rj   _DEFAULT_TIMERS_PATHr   rR   rS   rT   rU   itemsr   rs   rt   rw   rx   r   r   r   )rK   r   running_tasksrY   timers_datar_   
task_entrychecked_task_idsr   checktidr    ts                r$   get_unchecked_tasksr   B  s    $*$$&k39 +Q"iil+'2w'C'I'I'K #>>(+y8!(('.'1~~i'D I &)U??X(C': ,a#yy|H,%\\(B7 2E))I.C(,,S12 )QaAiL@P,PQQ9+ +$, , (('2 XRSTRUVWWX R <QC@A	s    F- EAF- )F- 5F- E* E40E* %E* 8F- =F(
F(F- EF- E'#E* *F%F F-  F%%F- -	G6GGG)NNN)NN)$__doc__ro   rS   osr   r   pathlibr   typingr   utils.loggerr   __name__r   ImportErrorlogging	getLoggerenvironrU   
_WORKSPACErk   rj   r   strhomerl   rr   listr%   r/   rJ   r]   booldictr   r   r7       r$   <module>r      s     	 	   )'!F "**..!13HIJ
!H,{: ),CC !H,/AA  JJNN#IDIIK)#j03ZZ]eef #[0 1$ 149 1hd tCy $/c / /$s) /d#T #c #R !# $x #xxx Tkx 	x
 +x x 
xx !#7Tk77 
$Z7]	  )Wx(F)s   D D98D9