
    [i-              
          d Z ddlZddlZdZg dZg dZ ej                  d      Z ej                  d      Z ej                  d       ej                  d	       ej                  d
       ej                  dej                         ej                  dej                        gZ
 ej                  dej                         ej                  d       ej                  d      gZ ej                  d       ej                  dej                         ej                  dej                         ej                  dej                         ej                  d      gZ ej                  d       ej                  d       ej                  d       ej                  d       ej                  d       ej                  dej                         ej                  dej                        gZ ej                  dej                        Z ej                  d      Z ej                  dej                         ej                  dej                         ej                  dej                        gZ ej                  d ej                        gZ ej                  d!ej                        Zd"ed#eeeef      fd$Zd%ee   d&ed#efd'Zd0d%ee   d"ed#eeeef      fd(Zd%ee   d)ed#efd*Zd0d+ed,ed#efd-Zd.ed#efd/Zy)1u   
critical_gap.py - 보고서 CRITICAL 이슈 미수정 검증 verifier

보고서에서 CRITICAL 이슈가 보고되었으나 수정이 확인되지 않으면 FAIL.
    Nz"/home/jay/workspace/memory/reports)CRITICALcriticalu   심각u	   블로커)u   수정 완료u   해결fixedresolvedz\b(CRITICAL|critical)\bu:   (?:^|[\s,。、!?])(?:심각|블로커)(?:[\s,。、!?]|$)u5   ^\s*#{1,6}\s+.*(?:CRITICAL|critical|심각|블로커)u3   ^\s*[-*]\s+.*(?:CRITICAL|critical|심각|블로커)u4   ^\s*\d+\.\s+.*(?:CRITICAL|critical|심각|블로커)zseverity\s*[:=]\s*criticalz(!\[(?:security-critical|critical|high)\]z\*\*\[.*resolved.*\]\*\*u   ✅\s*RESOLVEDu   ~~.*(critical|심각).*~~u   수정\s*완료z	\bfixed\bz\bresolved\bu>   해결(?:됨|되었|되었음|됐|책|책을|책이|\s*완료)u   미\s*해결u   미\s*완료u   해결\s*되지\s*않u   해결\s*안\s*됨u   해결\s*못
unresolvedznot\s+(?:fixed|resolved)ur   ^#{1,6}\s+(?:CRITICAL\s*이슈|발견된?\s*이슈|발견된?\s*문제|미해결\s*항목|문제점|이슈|issues)z
^#{1,6}\s+ul   ^\s*(?:-\s*)?(?:우선순위|priority|level|발사\s*우선순위|dispatch\s*level|작업\s*레벨)\s*[:：]z"^\s*(?:#{1,6}\s+)?\[CRITICAL\]\s*$z--level\s+criticalz:\bcritical\s+(?:path|chain|section|mass|period|thinking)\buG   level|priority|우선순위|\[CRITICAL\]|--level|dispatch|발사|발행contentreturnc                 "   g }d}t        | j                         d      D ]l  \  }}t        j                  |j	                               rd}|j                  ||f       ?|sBt        j                  |      rd}Z|j                  ||f       n |S )uu  
    보고서 전체 문자열에서 이슈 섹션 안의 줄들만 추출한다.

    Args:
        content: 보고서 전체 문자열

    Returns:
        (line_num, line) 튜플 리스트 — 이슈 섹션 헤더 제외, 섹션 내 모든 줄 포함.
        이슈 섹션 헤더를 만나면 수집 시작, 다른 마크다운 헤더를 만나면 수집 종료.
    F   startT)	enumerate
splitlines_ISSUE_SECTION_HEADERSmatchstripappend_ANY_HEADER)r   resultin_issue_sectionilines        :/home/jay/workspace/teams/shared/verifiers/critical_gap.py_extract_issue_sectionsr   l   s     %'FW//1; %4!''

5# MM1d)$  &#( MM1d)$% M    linesline_numc                     |dz
  }t        d|dz
        }t        t        |       |dz         }t        ||      D ]"  }||k(  r	t        j                  | |         s" y y)u  
    line_num(1-based) 줄 앞뒤 ±2 줄에 메타 키워드가 있으면 True.

    Args:
        lines: 전체 줄 목록 (0-indexed)
        line_num: 검사 기준 줄 번호 (1-based)

    Returns:
        True if metadata context detected in surrounding ±2 lines.
    r   r         TF)maxminlenrange_METADATA_CONTEXT_KEYWORDSsearch)r   r   idxr   endjs         r   _is_metadata_contextr*      sj     Q,C37OE
c%j#'
"C5# 8%,,U1X6	
 r   c                 v   g }|rt        |      }|sg S |}nt        t        | d            }|D ]  \  }t        j	                        st
        j	                        s2t        fdt        D              rKt        t        j                              }|rt               }t        D ]n  }|j                        D ]X  }	|	j                  d      j                         j                  d      }
|
dk\  s7|j                  |	j                         |
z          Z p |D 	ch c]  }	|	j                          }}	|r|j!                  |      rt#        | |      r,t        fdt$        D              sFt        fdt&        D              r`|j)                  |j+                         f        |S c c}	w )Nr   r   c              3   @   K   | ]  }|j                          y wNr&   .0pr   s     r   	<genexpr>z)_detect_critical_lines.<locals>.<genexpr>   s     <!qxx~<   r   r   c              3   @   K   | ]  }|j                          y wr-   r.   r/   s     r   r2   z)_detect_critical_lines.<locals>.<genexpr>   s     Aa188D>Ar3   c              3   @   K   | ]  }|j                          y wr-   r.   r/   s     r   r2   z)_detect_critical_lines.<locals>.<genexpr>   s     @!qxx~@r3   )r   listr   _CRITICAL_RE_ENr&   _CRITICAL_RE_KOany_META_LABEL_PATTERNSfinditerset_GENERIC_PHRASE_PATTERNSgrouplowerfindaddr   issubsetr*   ISSUE_MARKER_PATTERNSRESOLVED_INLINE_PATTERNSr   r   )r   r   foundissue_lines
candidatesr   critical_matchesgeneric_spansgpmcicritical_positionsr   s               @r   _detect_critical_linesrN      s   #%E -g6I 
)E34
$ /$&&t,0F0Ft0L<';<< 8 8 >?EM. :T* :A))+00<BQw%))!'')b.9	:: 6F!F!'')!F!F!&8&A&A-&Px0A+@AA@'?@@h

-.;/< L "Gs    F6critical_line_numc                     | |d D ]5  t        fdt        D              rt        fdt        D              s5 y y)u  
    critical_line_num 이후 줄에서 RESOLVED 마커 탐지. 부정 컨텍스트는 차단.

    Args:
        lines: 전체 줄 목록
        critical_line_num: CRITICAL 이슈가 발견된 줄 번호 (1-based)

    Returns:
        True if resolved marker found after critical_line_num (단, 같은 줄에
        부정 힌트가 있으면 해당 줄은 후보에서 제외).
    Nc              3   @   K   | ]  }|j                          y wr-   r.   r/   s     r   r2   z)_detect_resolved_after.<locals>.<genexpr>   s     9!qxx~9r3   c              3   @   K   | ]  }|j                          y wr-   r.   r/   s     r   r2   z)_detect_resolved_after.<locals>.<genexpr>   s     :!qxx~:r3   TF)r9   _UNRESOLVED_HINTS_RESOLVED_PATTERNS)r   rO   r   s     @r   _detect_resolved_afterrU      sF     '() 9'899:'9:: r   task_idreport_pathc                 x   | sddgdS |r|}n't         j                  j                  t        |  d      }t         j                  j	                  |      s	dd| gdS 	 t        |dd      5 }|j                         }d	d	d	       j                         }|r|j                         sddgdS t        ||      }|s	dd| gdS g }g }	|D ]d  \  }
}t        ||
      }t        |      }|r|j                  d|
 d|        7|j                  d|
 d|        |	j                  d|
 d|        f |	r$|j!                  ddt#        |	       d       d|dS |j!                  ddt#        |       d       d|dS # 1 sw Y   xY w# t        $ r)}dd
t        |      j                   d| gdcY d	}~S d	}~ww xY w)u  
    보고서에서 CRITICAL 이슈 확인 + 수정 여부 검증.

    보고서 경로: /home/jay/workspace/memory/reports/{task_id}.md
    - CRITICAL 이슈가 있는데 수정 확인이 없으면 FAIL
    - CRITICAL 이슈가 있고 수정 확인도 있으면 PASS
    - CRITICAL 이슈가 없으면 PASS (이슈 없음)
    - 보고서 파일 없으면 SKIP
    - 빈 보고서 → PASS

    Returns:
        {"status": "PASS"|"FAIL"|"WARN"|"SKIP", "details": [...]}
    SKIPzNo task_id provided)statusdetailsz.mdzReport not found: rzutf-8)encodingNzFailed to read report: z: PASSu&   Report is empty — no CRITICAL issuesz$No CRITICAL issues found in report: zCRITICAL (line z) RESOLVED: z) UNRESOLVED: zline r   u	   FAIL — z CRITICAL issue(s) not resolvedFAILu	   PASS — z CRITICAL issue(s) all resolved)ospathjoinDEFAULT_REPORTS_DIRexistsopenreadOSErrortype__name__r   r   rN   rU   _extract_issue_descriptionr   insertr#   )rV   rW   ra   fr   er   critical_linesr[   r   r   line_contentr   
issue_descs                 r   verifyrq      s
     .C-DEE ww||/G9CA 77>>$,TF34
 	

$g. 	!ffhG	  E  .V-WXX ,E7;N>tfEF
 	
 GJ"0 @,)%:/=
NN_XJl:,OPNN_XJnZLQRhZr*>?@ qIc*o%66UVW W55NN1	#n"5!66UVW11S	 	 
1$q'2B2B1C2aSIJ
 	

s6   F ,E;=F ;F F 	F9F4.F94F9r   c                     t        j                  dd|       j                         }t        |      dkD  r|dd dz   S |r|S | dd S )uA   CRITICAL 이슈 줄에서 설명 텍스트 추출 (최대 80자).z^[#\-*\d\.\s]+ P   Nu   …)resubr   r#   )r   cleaneds     r   rj   rj   3  sP     ff&D1779G
7|bs|e##7,49,r   )rs   )__doc__r`   ru   rc   CRITICAL_KEYWORDSRESOLVED_KEYWORDScompiler7   r8   
IGNORECASErC   rD   rT   rS   r   r   r:   r=   r%   strr6   tupleintr   boolr*   rN   rU   dictrq   rj    r   r   <module>r      sI   
 	:  D  E  "**78"**Z[ BJJGHBJJEFBJJFGBJJ,bmm<BJJ:BMMJ  BJJ*BMM:BJJ !BJJ+,  BJJ!"BJJ|R]]+BJJ.BJJ "--0 BJJPQ	  BJJBJJBJJ'(BJJ$%BJJBJJ}bmm,BJJ*BMM:  $	 MM  bjj' BJJw
 BJJ4bmmDBJJ$bmm4  BJJE
  (RZZNMM S T%S/-B <S	 S T 0+$s) +c +4cSVhCX +\$s)   .I2C I2c I24 I2X-S -S -r   