
    i,                        d Z ddlZddlZddlZddlmZ ddlZej                  j                  dd       ddl	m
Z
  ej                  d      Z ej                  d      Zdded	ed
efdZdded	ed
efdZd Zd Zd Zd Zd Zd Zd Zd Zy)uy   Progressive Disclosure 레이어 기능 테스트

TC13 ~ TC20: search() layer 파라미터 및 get_by_ids() API 검증.
    N)Pathz/home/jay/workspace)MemoryIndexeruc      ---
    date: "2026-04-05"
    session: 1
    team_id: "dev3"
    task_id: "task-9999"
    tags: [auto-compact, pre-compact]
    auto_generated: true
    ---
    ## 수행한 작업
    - 메모리 인덱서 TDD RED phase 작성
    - SQLite FTS5 테이블 설계 검토

    ## 피드백 및 수정 지시
    - 한국어 검색 성능 확인 필요
u      ---
    name: 위임 규칙 종합
    description: 파일 기반 위임, 논리적 팀, 한정승인 등
    type: feedback
    team_id: "dev3"
    ---
    ### 파일 기반 위임 (절대 규칙)
    - 지시 내용 → 파일 작성 → `--task-file`로 전달.
    - 100자 이내만 `--task` 허용.

    ### 논리적 팀
    - 마케팅/컨설팅/출판/디자인 라우팅 규칙 준수.
	directoryfilenamereturnc                 >    | |z  }|j                  t        d       |S )u+   임시 디렉토리에 diary 파일 생성.utf-8encoding)
write_textDIARY_CONTENTr   r   fs      N/home/jay/workspace/.worktrees/task-2116-dev1/tests/test_memory_progressive.pymake_diary_filer   6   s!    HALLL1H    c                 >    | |z  }|j                  t        d       |S )u,   임시 디렉토리에 memory 파일 생성.r	   r
   )r   MEMORY_CONTENTr   s      r   make_memory_filer   =   s!    HALL'L2Hr   c           
      &   t        | dz        }t        |       }t        |      }	 |j                  t        |             |j	                  dd      }|j                          t        |t              sJ d       t        |      dkD  sJ d       h d	}h d
}|D ]`  }|D ]*  }||v rJ d| dt        |j                                        |D ]*  }||vrJ d| dt        |j                                        b y# |j                          w xY w)uS   layer='index' 검색 결과에는 id, title, type, score만 포함되어야 한다.test.dbdb_path   위임 규칙indexlayer3   search()가 리스트를 반환하지 않습니다.r   u2   layer='index' 검색 결과가 비어있습니다.>   idtypescoretitle>   tagssnippetteam_id	file_pathu'   layer='index' 결과에 필수 필드 '   '가 없습니다: u;   layer='index' 결과에 포함되어서는 안 될 필드 '   '가 있습니다: N)
strr   r   
index_filesearchclose
isinstancelistlenkeys)	tmp_pathr   mem_fileindexerresultsrequired_fieldsforbidden_fieldsitemfields	            r   test_TC13_layer_index_fieldsr9   I   s:   (Y&'G)HG,G3x=)...@gt$[&[[$w<!QQQ6OB {$ 	zED=y$KE7Refjkoktktkvfwex"yy=	z% 	{ET!{LUGSfgklplululwgxfyz{!	{{ 	s   -C> >Dc           
         t        | dz        }t        |       }t        |      }	 |j                  t        |             |j	                  dd      }|j                          t        |t              sJ d       t        |      dkD  sJ d       h d	}h d
}|D ]  }|D ]*  }||v rJ d| dt        |j                                        |D ]*  }||vrJ d| dt        |j                                        |j                  dd      }	t        |	      dk  rJ dt        |	       d|	        y# |j                          w xY w)u   layer='summary' 결과에는 id, title, type, score, snippet이 있어야 하고
    snippet은 50자 이하여야 한다. file_path, team_id, tags는 없어야 한다.r   r   r   summaryr   r   r   u4   layer='summary' 검색 결과가 비어있습니다.>   r   r    r!   r"   r$   >   r#   r%   r&   u)   layer='summary' 결과에 필수 필드 'r'   u=   layer='summary' 결과에 포함되어서는 안 될 필드 'r(   r$    2   u5   layer='summary' snippet이 50자를 초과합니다: u   자 → N)r)   r   r   r*   r+   r,   r-   r.   r/   r0   get)
r1   r   r2   r3   r4   r5   r6   r7   r8   r$   s
             r   test_TC14_layer_summary_fieldsr?   i   s~    (Y&'G)HG,G3x=)..	.Bgt$[&[[$w<!SSSAO7 }$ 	|ED={$MeWTghlmqmvmvmxhygz"{{=	|% 	}ET!}NugUhimnrnwnwnyizh{|}!	} ((9b)7|r!|%Z[^_f[gZhhpqxp{#||!} 	s   -D4 4Ec           
      R   t        | dz        }t        |       }t        |      }	 |j                  t        |             |j	                  dd      }|j	                  d      }|j                          t        |t              sJ d       t        |      dkD  sJ d       h d	}|D ]1  }|D ]*  }||v rJ d
| dt        |j                                        3 t        j                  |dd      t        j                  |dd      k(  sJ d       y# |j                          w xY w)u   layer='full' 결과에는 file_path, title, type, team_id, tags, snippet, score가
    모두 있어야 하고, layer 미지정 결과와 동일해야 한다.r   r   r   fullr   u@   layer='full' search()가 리스트를 반환하지 않습니다.r   u1   layer='full' 검색 결과가 비어있습니다.>   r#   r    r!   r"   r$   r%   r&   u&   layer='full' 결과에 필수 필드 'r'   FT)ensure_ascii	sort_keysu>   layer='full' 결과와 layer 미지정 결과가 다릅니다.N)r)   r   r   r*   r+   r,   r-   r.   r/   r0   jsondumps)	r1   r   r2   r3   results_fullresults_defaultr5   r7   r8   s	            r   "test_TC15_layer_full_compatibilityrH      s9    (Y&'G)HG,G3x=)~~oV~D!..9lD)m+mm)|q U"UU [O y$ 	yED=x$J5'Qdeijnjsjsjuevdw"xx=	yy
 ::l$G4::etL  HGH  	s   >D D&c                    t        | dz        }t        |      }	 t        j                  t              5  |j                  dd       ddd       |j                          y# 1 sw Y   xY w# |j                          w xY w)u=   layer='invalid' 전달 시 ValueError가 발생해야 한다.r   r   r   invalidr   N)r)   r   pytestraises
ValueErrorr+   r,   )r1   r   r3   s      r   test_TC16_invalid_layer_raisesrN      sh    (Y&'GG,G]]:& 	=NN?)N<	= 		= 	= 	s"   A. A"	A. "A+'A. .B c                    t        | dz        }t        |       }t        |       }t        |      }	 |j	                  t        |             |j	                  t        |             |j                  dd      }|j                  dd      }t        |      dkD  sJ d       t        |      dkD  sJ d	       |d   d
   }|d   d
   }|j                  ||g      }	|j                          t        |	t              sJ d       t        |	      dk(  sJ dt        |	       d       |	D ]'  }
d|
v rJ dt        |
j                                        y# |j                          w xY w)u`   파일 2개를 인덱싱한 뒤 get_by_ids()로 조회하면 content 필드가 있어야 한다.r   r   u   메모리 인덱서r   r   r   r   u+   diary 파일 검색 결과가 없습니다.u,   memory 파일 검색 결과가 없습니다.r   u7   get_by_ids()가 리스트를 반환하지 않습니다.   u:   get_by_ids([id1, id2]) 결과 건수가 2여야 하는데 u
   입니다.contentu9   get_by_ids() 결과에 'content' 필드가 없습니다: N)r)   r   r   r   r*   r+   r/   
get_by_idsr,   r-   r.   r0   )r1   r   
diary_filer2   r3   diary_resultsmem_resultsid1id2fetchedr7   s              r   test_TC17_get_by_ids_basicrY      su   (Y&'G *J)HG,G3z?+3x=)  '<GLnn_GnD=!A%T'TT%;!#S%SS#At$!nT"$$c3Z0gt$_&__$w<1s Z[^_f[gZhhrss rD q$]^bcgclclcn^o]p"qq r	 	s   B'E E!c                     t        | dz        }t        |      }	 |j                  g       }|j                          t	        |t
              sJ d       |g k(  s
J d|        y# |j                          w xY w)u7   get_by_ids([])는 빈 리스트를 반환해야 한다.r   r   u9   get_by_ids([])가 리스트를 반환하지 않습니다.uA   get_by_ids([])가 빈 리스트를 반환하지 않았습니다: Nr)   r   rR   r,   r-   r.   r1   r   r3   results       r   test_TC18_get_by_ids_emptyr^      sw    (Y&'GG,G##B'fd#`%``#R<e\]c\dee< 	s   A$ $A6c                     t        | dz        }t        |      }	 |j                  dg      }|j                          t	        |t
              sJ d       |g k(  sJ d| d       y# |j                          w xY w)uS   get_by_ids([99999])는 해당 ID가 없으면 빈 리스트를 반환해야 한다.r   r   i u>   get_by_ids([99999])가 리스트를 반환하지 않습니다.uJ   존재하지 않는 ID 조회 시 빈 리스트를 반환해야 하는데 u   를 반환했습니다.Nr[   r\   s       r    test_TC19_get_by_ids_nonexistentr`      s    (Y&'GG,G##UG,fd#e%ee#R<  Feflem  nE  F  F< 	s   A& &A8c                 R   t        | dz        }t        |       }t        |       }t        |      }	 |j	                  t        |             |j	                  t        |             |j                  dd      }|j                  dd      }|j                  dd      }|j                          dt        fd	} ||      }	 ||      }
 ||      }|	|
k  sJ d
|	 d|
 d       |
|k  sJ d|
 d| d       |	|z  }|dk  sJ d|dd|	 d| d       y# |j                          w xY w)u   같은 검색어로 layer='index' < 'summary' < 'full' 순으로 바이트 크기가
    증가해야 하며, full 대비 index의 크기가 50% 이하여야 한다.r   r   u   위임r   r   r;   rA   r   c                 `    t        t        j                  | d      j                  d            S )NF)rB   r	   )r/   rD   rE   encode)objs    r   	byte_sizez2test_TC20_token_saving_by_layer.<locals>.byte_size  s#    4::c6==gFGGr   zindex(u   B) 크기가 summary(u   B) 이상입니다.zsummary(u   B) 크기가 full(g      ?u;   full 대비 index 크기 비율이 50%를 초과합니다: z.1%z (index=zB, full=zB)N)r)   r   r   r   r*   r+   r,   int)r1   r   rS   r2   r3   results_indexresults_summaryrF   re   
size_indexsize_summary	size_fullratios                r   test_TC20_token_saving_by_layerrm     s\    (Y&'G *J)HG,G3z?+3x=)xw?!...C~~hf~=H# H =)J_-L,'I$qzl:OP\~]p&qq$)#nx~=OPY{Zm%nn#"EC< 
EeC[P\]g\hhpqzp{{}~< 	s   A-D D&)z2026-04-05-session-01.md)zdelegation_rules.md)__doc__rD   systextwrappathlibr   rK   pathinsertutils.memory_indexerr   dedentr   r   r)   r   r   r9   r?   rH   rN   rY   r^   r`   rm    r   r   <module>rw      s   
  
    ( ) .   ! " ! "  t s TX   PT {@}FHB	"rHf&F&r   