
    iC              
      H   U d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z	ddl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Z eej(                  j+                  d e ee      j1                         j2                  d                     Zedz  Z ee      ej8                  vr"ej8                  j;                  d ee             edz  d	z  Zed
z  Zedz  dz  dz  Z edz  dz  dz  dz  Z! ed      Z"i Z#de$d<   ddZ%d Z&ddZ'd dZ(d!d"dZ)d Z*d Z+d Z,d Z-d Z.d Z/d Z0y)#u;  task-2403 — IDS 후속 정리 통합 회귀 테스트 (벨레스 작성).

커버 항목:
1. task-2391/2392/2394 .done 발급 확인
2. task-2392 28장 PNG 한글 OCR 100% (계층 표본 + rapidocr)
3. task-2393 5 mp4 첫·중·끝 OCR 100%
4. task-2394 router 5 자연어 케이스 라우팅 정확도 ≥ 80%
5. silent pass 게이트 회귀 (더미 PNG → OCR 키워드 0건 → FAIL 판정)

★ silent pass 금지: 파일 존재만으로 PASS 판정하지 않는다.
★ rapidocr 미설치 환경: 명확한 FAIL 메시지로 신호 (silent fallback PASS 금지).
    )annotationsN)PathWORKSPACE_ROOT   scriptsmemoryeventsarchiveskillszmobile-prototype-kooutputszvalidate_korean_ocr.pyz/tmp/task-2403-motiondict_OCR_ENGINE_CACHEc                     	 t        j                  d       y# t        $ r) 	 t        j                  d       Y y# t        $ r Y Y yw xY ww xY w)u  사용 가능한 OCR 엔진 종류 반환.

    Returns:
        "easyocr" — easyocr 사용 (한국어 정확도 높음)
        "rapidocr" — rapidocr fallback (중국어 PPOCR 모델, 한국어 미지원)
        "none" — OCR 미설치 (silent pass 금지: 명시 FAIL)
    easyocrrapidocr_onnxruntimerapidocrnone)	importlibimport_moduleImportError     ;/home/jay/workspace/tests/dev6/test_ids_followup_cleanup.py_ocr_engine_kindr   7   sP    	* 	##$:; 			s$    	A
9	AA
AA
c                     t               } | dk(  ry| t        v rt        |    | fS | dk(  rddl}|j                  ddgdd	      }ndd
lm}  |       }|t        | <   || fS )uJ   OCR 엔진 인스턴스 반환. 캐시 사용 (모델 init 비용 절감).r   )Nr   r   r   NkoenF)gpuverbose)RapidOCR)r   r   r   Readerr   r    )kindr   enginer    s       r   	_load_ocrr$   J   so    Dv~   &,,yt%G1$d4<r   c                    |dk(  r| j                  t        |      d      S |dk(  r= | t        |            \  }}|sg S |D cg c]  }|st        |      dkD  s|d    c}S g S c c}w )u1   OCR 실행 → 인식된 텍스트 목록 반환.r   r   )detailr      )readtextstrlen)r#   r"   png_pathresult_items         r   _run_ocrr/   [   so    ys8}Q77z3x=)	I$*EDds4y1}QEEI Fs   A&A&A&c                     t         j                  j                  dt              } t         j                  j	                  |       }| j
                  j                  |       |j                  S )Nvalidate_korean_ocr)r   utilspec_from_file_locationVALIDATE_OCR_SCRIPTmodule_from_specloaderexec_moduleSCENARIO_KEYWORDS)specmods     r   _load_scenario_keywordsr;   l   sP    >>112D ..
)
)$
/CKKC    r   c           
        dd}d}t        j                  d||ddddd      } |d|      }d}t        |      D ]  }d	d
|z  z   }	||	z  } t        j                  |      }
 |d|
      } |dd      }| j                  ||z   |z   |z          y)u:   흰색 10×10 PNG 파일 생성 (한글 텍스트 없음).c                    | |z   }t        j                  dt        |            |z   t        j                  dt        j                  |      dz        z   S )Nz>Il    )structpackr*   zlibcrc32)
chunk_typedatacs      r   _chunkz_make_dummy_png.<locals>._chunk}   sD    {{4T+a/&++dDJJqMT^D^2___r   s   PNG

z>IIBBBBB   r   r   s   IHDRr       s   s   IDATs   IENDN)rB   bytesrC   rH   returnrH   )r>   r?   ranger@   compresswrite_bytes)pathwidthheightrE   header	ihdr_dataihdrraw_rowsr-   row
compressedidatiends                r   _make_dummy_pngrX   z   s    ` "FJvq!Q1EI'9%DH6] %//C x(J':&D'3DVd]T)D01r   c            	        g d} g }| D ]V  }t         | dz  t        | dz  t         | dz  t        | dz  g}t        d |D              }|rF|j                  |       X | }|st	        j
                  d| dt          dt         d      d	z   d
dt        j                         v st	        j                  |      rt	        j                  |      ndiz  }t        t	        j                  |            d}y)ua   task-2391, 2392, 2394 의 .done 파일이 events/ 또는 events/archive/ 에 존재해야 한다.)z	task-2391z	task-2392z	task-2394z.donez.done.ackedc              3  <   K   | ]  }|j                           y w)N)exists).0ps     r   	<genexpr>z<test_done_files_issued_for_2391_2392_2394.<locals>.<genexpr>   s     31AHHJ3s   u=   다음 task의 .done 파일이 발급되지 않았습니다: u   
  확인 경로: u    및 u3   
  finish-task.sh 실행 여부를 점검하세요.
>assert not %(py0)spy0missingN)
EVENTS_DIREVENTS_ARCHIVE_DIRanyappend
@pytest_ar_format_assertmsg@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)task_idsra   tid
candidatesfound@py_assert1@py_format2s          r   )test_done_files_issued_for_2391_2392_2394rt      s    7HG 
  C5&C5.C5,,C5!44	

 3
33NN3
  ; ;   Hy Q&<u-?,@ A=	=  	  	    	     	 r   c                 .   t        t        j                  d            } t        |       }d}||k\  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dz  }t	        j                  d| dt         d	      d
z   d|iz  }t        t	        j                  |            dx}}g d}|D ]  }t        t        j                  | d            }|st	        j                  d| dt               dz   ddt        j                         v st	        j                  |      rt	        j                  |      ndiz  }	t        t	        j                  |	            |d   }
|
j                         j                  dz  }d}||kD  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dz  }t	        j                  d|
j                    d|dd      d
z   d|iz  }t        t	        j                  |            dx}} y)ui   outputs/ 디렉토리에 PNG가 28장 존재하고 표본 3장 크기가 각각 10KB 초과여야 한다.*.png   >=z%(py0)s >= %(py3)sactual_countr`   py3u   PNG 파일이 u5   장입니다 (기대: 28장 이상).
  디렉토리: u<   
  스바로그가 아직 렌더링 중일 수 있습니다.
>assert %(py5)spy5Ndashboard_iphone15pro_lightsignup_step1_pixel9pro_darkai_analysis_iphone15pro_darku   표본 PNG 'u/   ' 를 찾을 수 없습니다.
  디렉토리: 
>assert %(py0)sr`   matchesr      
   )>)z%(py0)s > %(py3)ssize_kb'u   ' 크기가 z.1fuk   KB — 10KB 미만.
  한글이 그려지지 않았거나 렌더링이 실패한 것으로 의심됩니다.)sortedOUTPUTS_DIRglobr*   rf   _call_reprcomparerh   ri   rj   rk   rg   rl   rm   liststatst_sizename)	png_filesr{   @py_assert2rr   @py_format4@py_format6sample_stemsstemr   @py_format1pngr   s               r   !test_png_28_count_and_sample_sizer      s_    {''01Iy>L <2  	<2   	  	    	    	      '&- (F	F   	 L
  
{''4&78 	
  4& !*m-	
 	
 
6	
 	
   	
 	
 
	  	
 	
 	
 	
 	
 aj((*$$t+ 	
w| 	
 	
w 	
 	
 
6	
 	
   	
 	
 
	  	
 	
 
	  	
 	
  zgc] 3f f	
 	
 	
 	
 	

r   c                    t               \  } }| t        j                  d       t               }dddd}t	        j
                  d      }g }|j                         D ]  \  }}t        t        j                  | d            }|s|j                  d	| d
       ?|d   }	t        | ||	      }
dj                  |
      }|j                  |g       }|D cg c]	  }||v s| }}t        |j                  |            }|r|j                  d|	j                    d| d| d|dd         | }|st#        j$                  ddj                  |      z   dz         dz   ddt'        j(                         v st#        j*                  |      rt#        j,                  |      ndiz  }t/        t#        j0                  |            d}yc c}w )u   표본 PNG 3장에 대해 rapidocr로 한글 키워드 존재를 검증한다.

    ★ rapidocr 미설치 환경: FAIL (silent pass 금지).
      - 파일 크기만으로 PASS 처리하지 않는다.
    Nu   [rapidocr 미설치] rapidocr_onnxruntime 패키지가 설치되어 있지 않습니다.
  한글 OCR 검증을 건너뛰면 silent pass가 됩니다 — 이는 허용되지 않습니다.
  pip install rapidocr-onnxruntime 후 재실행하세요.	dashboardsignup_step1ai_analysisr   u	   [가-힣]rv   u     파일 없음: u    (outputs/에서 찾지 못함)r    z  u   : 시나리오='uB   ' 한글 OCR 0건 (시각 corruption 의심)
    matched_keywords=u$   
    OCR 텍스트 (처음 200자):    u3   PNG 한글 OCR 시각 corruption 게이트 실패:

u]   
  (정밀 키워드 매칭 정확도는 memory/reports/task-2403-easyocr-verify.json 참조)r_   r`   failures)r$   pytestfailr;   recompileitemsr   r   r   re   r/   joingetboolsearchr   rf   rg   rh   ri   rj   rk   rl   rm   )ocrocr_kindscenario_keywords
sample_map	HANGUL_REr   r   scenarior   r+   textscombinedexpected_kwskwmatched_keywords
any_hangulrr   rs   s                     r   (test_png_sample_rapidocr_korean_keywordsr      s    KMC
{I	
 01 (3'5(5J 

<(IH$**, h{''4&78OO/v5TUV1:h188E? ),,Xr:)5H2xBHH )**845
OOX]]O#3H: >((8'9 :66>tn5GI%2 < <   	?8ATTh	i               Is   	GGc            	        t         j                  }  |        }|st        j                  dt          d      dz   dt	        j
                         v st        j                  t               rt        j                  t               ndt        j                  |       t        j                  |      dz  }t        t        j                  |            dx} }t        t         j                  d            }t        t         j                  d            }t        |      d	k\  }t        |      d
k\  }g } |}|s|}|s&dddt	        j
                         v st        j                  |      rt        j                  |      ndiz  }| j                  |       |sXdddt	        j
                         v st        j                  |      rt        j                  |      ndiz  }| j                  |       t        j                  | d      i z  }	t        j                  dt        |       dt        |       dt          d      dz   d|	iz  }
t        t        j                  |
            dx}} y)u   /tmp/task-2403-motion/ 에 mp4 5건 또는 PNG 15장이 존재해야 한다.

    ★ 디렉토리 미존재 시 skip이 아닌 명확한 FAIL로 신호.
    u9   모션 출력 디렉토리가 존재하지 않습니다: u   
  task-2393 산출물이 아직 생성되지 않았거나 경로가 변경되었습니다.
  glob 패턴으로 /tmp/task-2403-motion/**/*.mp4 및 *.png 를 확인하세요.zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}
MOTION_DIR)r`   py2py4Nz**/*.mp4**/*.png      z%(py2)sr   has_mp4z%(py4)sr   
has_framesr'   zmp4(u   건) 또는 PNG 프레임(u_   장) 모두 부족합니다.
  기대: mp4 5건 이상 또는 PNG 15장 이상
  디렉토리: u?   
  스바로그 mp4 렌더링 완료 여부를 확인하세요.z
>assert %(py7)spy7)r   r[   rf   rg   rh   ri   rj   rk   rl   rm   r   r   r*   re   _format_boolop)rr   @py_assert3@py_format5	mp4_files
png_framesr   r   @py_assert0@py_format3r   @py_format8s              r   test_motion_mp4_or_frames_existr     s         DJ< P\ 	\  	  	    	    	    	     	  zz23I

34J)n!GZB&J7 7j  
  
    
    
 
  
  
  !  
  !  
 

  
 	 s9~8Z8I J%, 'I	I  
  r   c            
        t         j                         st        j                  dt          d       t	               \  } }| t        j                  d       t        t         j                  d            t        t         j                  d            z   t        t         j                  d            z   }|st        j                  dt          d	      d
z   ddt        j                         v st        j                  |      rt        j                  |      ndiz  }t        t        j                  |            |d   }t        | ||      }dj!                  |      }g d}|D cg c]	  }||v s| }	}|	st        j                  d|j"                   d| d|dd       d
z   ddt        j                         v st        j                  |	      rt        j                  |	      ndiz  }t        t        j                  |            yc c}w )u   모션 표본 1건에 대해 rapidocr로 한글 키워드 존재를 검증한다.

    ★ rapidocr 미설치 환경: FAIL (silent pass 금지).
    u&   모션 출력 디렉토리 미존재: uA   
  test_motion_mp4_or_frames_exist 먼저 통과해야 합니다.Nu   [rapidocr 미설치] rapidocr_onnxruntime 패키지가 설치되어 있지 않습니다.
  모션 OCR 검증을 건너뛰면 silent pass가 됩니다 — 허용되지 않습니다.
  pip install rapidocr-onnxruntime 후 재실행하세요.z**/*first*.pngz
**/*_0.pngr   u1   모션 PNG 프레임을 찾을 수 없습니다: z	/**/*.pngr   r`   rp   r   r   )u	   보험료u   비교u   안내AIu   분석u   점수u   카드뉴스u   발행u?   모션 표본 OCR 키워드 없음 (시각 corruption 의심): u:   
  기대 키워드 (모션 슬라이드 3장 합집합): u"   
  OCR 텍스트 (처음 200자): r   rq   )r   r[   r   r   r$   r   r   rf   rg   rh   ri   rj   rk   rl   rm   r/   r   r   )
r   r   rp   r   
sample_pngr   r   candidate_kwsr   rq   s
             r   test_motion_sample_rapidocrr   0  s    4ZL AO O	

 KMC
{I	
 	z/01
.
/	0
,
-	. 
    <J<yQ               AJS(J/ExxH jM':B2>R:E:   J*//IZ [DDQ? S,,4TcN+=	?  	  	    	     	 5 ;s   "	H,Hc                    t        j                  d      } g d}d}g }|D ]m  \  }}| j                  |d      }|j                  |k(  r|dz  }.|j	                  d|d|d	|j                  d
|j
                  d|j                  dd       o |t        |      z  }d}||k\  }	|	st        j                  d|	fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }
t        j                  d| dt        |       d|dddj                  |      z         dz   d|
iz  }t!        t        j"                  |            dx}	}y)u   5개 자연어 입력 → 각 라우팅 결과 정답률 ≥ 80% (5건 중 4건 이상).

    ids_natural_routing.route()를 importlib로 직접 호출.
    ids_natural_routing))u)   인스타그램 카드뉴스 만들어줘cardnews)u.   iPhone 15 Pro 모바일 프로토타입 시연mobile)u"   supabase 스타일 보험 PPT 5장ppt)u#   MP4 모션 카드뉴스 reels 30초motion)u%   광고 포토 이미지 한글 카피imager   design_team)callerr'   u     프롬프트=u   
    기대 intent=u   
    실제 intent=z (skill=z, conf=z.2f)g?rx   rz   accuracyr|   u   라우팅 정확도 /z (z.0%u(   ) — 기대: ≥ 80%
미스 케이스:
r   r~   r   N)r   r   routeintentre   skill
confidencer*   rf   r   rh   ri   rj   rk   rg   r   rl   rm   )
ids_router
test_casescorrectmissespromptexpected_intentdecisionr   r   rr   r   r   s               r   $test_router_natural_language_5_casesr   c  s    (()>?JJ GF#- 	##F=#A??o-qLGMM!& ,%%4$7 8%%-__$7x?QQXYaYlYlmpXqqrt	 Z(H 8t  8t                  wiqZ(9HS> J 	 $		& 1	2    r   c                    t               \  } }| t        j                  d       t               }|j	                  dg d      }t        j                         5 }t        |      dz  }t        |dd       |j                         j                  }d}d}||z  }	||	k  }
|
st        j                  d	|
fd
||	f      dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |      dz  }t        j"                  d| d      dz   d|iz  }t%        t        j&                  |            dx}
x}x}}	t)        | ||      }dj+                  |      }|D cg c]	  }||v s| }}| }
|
st        j"                  d| d| d      dz   ddt        j                         v st        j                  |      rt        j                   |      ndiz  }t%        t        j&                  |            d}
ddd       yc c}w # 1 sw Y   yxY w)uv  더미 PNG (한글 0) → rapidocr OCR → 키워드 0건 → FAIL이어야 한다.

    이 테스트 자체가 PASS 되어야 한다 (더미 PNG로 FAIL이 나는지 확인하는 메타 회귀).
    즉, OCR 키워드가 0건임을 assert 하여 "파일 존재만으로 PASS 되지 않음"을 보장.

    ★ rapidocr 미설치 환경: FAIL (silent fallback 불허).
    Nu!  [rapidocr 미설치] silent pass 게이트 회귀 테스트를 실행할 수 없습니다.
  rapidocr_onnxruntime 미설치 상태에서 더미 PNG 검증을 건너뛰면
  'silent pass 금지' 원칙이 보장되지 않습니다.
  pip install rapidocr-onnxruntime 후 재실행하세요.r   )u   보험u   월u   원u   추천zdummy_no_korean.pngr   )rN   rO   r   )<)z%(py0)s < (%(py3)s * %(py5)s)
size_bytes)r`   r}   r   u    더미 PNG가 너무 큽니다: u   B — 테스트 설계 오류z
>assert %(py8)spy8r   u%   게이트 회귀 오류: 더미 PNG (u$   B, 한글 없음)에서
  키워드 uz   가 발견되었습니다.
  OCR 엔진이 오탐(false positive)을 내거나 테스트 설계를 점검해야 합니다.r_   r`   	found_kws)r$   r   r   r;   r   tempfileTemporaryDirectoryr   rX   r   r   rf   r   rh   ri   rj   rk   rg   rl   rm   r/   r   )r   r   r   r   tmpdir	dummy_pngr   r   @py_assert4@py_assert6rr   @py_format7@py_format9r   r   r   r   rs   s                     r   .test_silent_pass_gate__dummy_png_must_fail_ocrr     s5    KMC
{I	
 01$((6XYL		$	$	& 
&L#88		B7 ^^%--
 	
 	
BI 	
zI% 	
 	
zI 	
 	
	6	
 	
   	
 	
 		  	
 	
 		  	
 	
 		 "& 	
 	
  /zl:WX	
 	
 	
 	
 	
 	
 h	288E?".AB".RA	A } 	
} 	
  4J< @$+ &nn	
 	
 
6		
 	
 	  	
 	
 
		  	
 	
 	
 		
 	

 
 B
 
s&   D8H6	H1H1BH61H66H?)rI   r)   )r"   r)   r+   r   rI   z	list[str])rI   r   )r   r   )rM   r   rN   intrO   r   rI   None)1__doc__
__future__r   builtinsrh   _pytest.assertion.rewrite	assertionrewriterf   r   importlib.utilosr   r>   sysr   r@   pathlibr   r   environr   r)   __file__resolveparentsr   SCRIPTSrM   insertrb   rc   r   r4   r   r   __annotations__r   r$   r/   r;   rX   rt   r   r   r   r   r   r   r   r   r   <module>r     sG   #      	 	  
     JJNN#Sh)?)?)A)I)I!)L%MN 9
$w<sxxHHOOAs7|$h&1
)+ x'*??)KX 55	AD\\  )*
  4 &"	"!26<
@:D6+f#V(
r   