
    Gi8                       d Z ddlm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                  j                  Zej                  j                  d ee             ddlmZmZmZmZ ddZdddZ G d d	      Zdd
ZddZddZ G d d      Ze	j:                  d        Z G d d      Zy)u  
test_memory_enforcement.py

task-2419 통합 회귀 테스트:
- Fix 1: scripts/hooks/pre-commit-memory-check.py (★ 마커 의무 검증)
- Fix 2: scripts/memory_violation_detector.py (위반 자동 감지 CLI)
- Fix 3: utils/memory_check.py 스키마 확장 (pending/acknowledged/structured)

격리: pytest tmp_path + 환경변수 override (WORKSPACE_ROOT, MEMORY_CHECK_FEEDBACK_DIR)
회귀 0: 기존 issue_mc 정상 발급 + memory_items_read 평면 배열 유지
    )annotationsN)Path)ack_mcget_mc_by_taskget_pending_mcsissue_mcc                $   | dz  }|j                          t        j                  g d|d       t        j                  g d|d       t        j                  g d|d       |dz  j                          |dz  dz  j                  d	d
       |S )u3   임시 git repo 초기화. workspace 구조 모방.repo)gitinit-qTcwdcheck)r   configz
user.emailzt@t)r   r   z	user.nametmemory	MEMORY.mdu   # WS Memory
- 일반 항목
utf-8encoding)mkdir
subprocessrun
write_text)tmp_pathr
   s     N/home/jay/workspace/.worktrees/task-2444-dev2/tests/test_memory_enforcement.py
_init_repor   '   s    fDJJLNN(d$?NN9t4PNN6DM	H_	H_{"..(7 /  K    c                :   t         dz  dz  dz  }t        j                  j                         }t	        |       |d<   t	        | dz        |d<   |r|j                  |       t        j                  dt	        |      g| dd|	      }|j                  |j                  fS )
uL   pre-commit-memory-check.py를 임시 repo에서 실행. (exit_code, stderr).scriptshookszpre-commit-memory-check.pyWORKSPACE_ROOTanu_memory_nonexistMEMORY_CHECK_FEEDBACK_DIRpython3Tr   capture_outputtextenv)
r#   osenvironcopystrupdater   r   
returncodestderr)r
   	env_extra	hook_pathr*   results        r   _run_precommitr5   5   s    *W47SSI
**//
CIC'*42G+G'HC#$

9^^	C	N#F fmm++r   c                  $    e Zd Zd Zd Zd Zd Zy)TestFix1PreCommitMemoryCheckc                    t        |      }|dz  }|j                  dd       t        j                  g d|d       t	        |      \  }}|dk(  sJ d|v sJ y	)
u7   신규 feedback_*.md 파일 + ★ 미등록 → exit 1.feedback_new_rule.md   새 피드백
r   r   )r   addr9   Tr      Nr   r   r   r   r5   )selfr   r
   fbcodeerrs         r    test_block_unregistered_feedbackz=TestFix1PreCommitMemoryCheck.test_block_unregistered_feedbackH   sa    (#**
'':=4tT"4(	cqyy%,,,r   c                    t        |      }|dz  dz  j                  dd       |dz  }|j                  dd       t        j                  g d|d	
       t	        |      \  }}|dk(  sJ y)u9   ★ 마커로 MEMORY.md에 등록된 feedback → exit 0.r   r   u4   # WS Memory
★ feedback_new_rule.md — 신규 룰
r   r   r9   r:   )r   r;   zmemory/MEMORY.mdr9   Tr   r   Nr=   r>   r   r
   r?   r@   _s         r   test_pass_when_registeredz6TestFix1PreCommitMemoryCheck.test_pass_when_registeredT   sx    (#	;	&22Dw 	3 	
 **
'':QW[cgh &aqyyr   c                    t        |      }|dz  }|j                  dd       t        j                  g d|d       t	        |dd	i
      \  }}|dk(  sJ y)u2   SKIP_MEMORY_CHECK=1 → 미등록이어도 exit 0.feedback_emergency.mdu   긴급
r   r   )r   r;   rH   Tr   SKIP_MEMORY_CHECK1)r2   r   Nr=   rD   s         r   test_skip_env_bypassz1TestFix1PreCommitMemoryCheck.test_skip_env_bypassb   s[    (#++
j73>DPTU 2Es1KLaqyyr   c                    t        |      }|dz  }|j                  dd       t        j                  g d|d       t	        |      \  }}|dk(  sJ y	)
u4   feedback_test_*.md 패턴 → 검사 제외, exit 0.feedback_test_fixture.mdztest fixture
r   r   )r   r;   rM   Tr   r   Nr=   rD   s         r   test_test_files_excludedz5TestFix1PreCommitMemoryCheck.test_test_files_excludedm   sT    (#..
&9AtSWX &aqyyr   N)__name__
__module____qualname__rB   rF   rK   rN    r   r   r7   r7   G   s    
-		r   r7   c                   t         dz  dz  }t        j                  j                         }t	        |       |d<   t        j                  dt	        |      g|| dd|      }|j                  |j                  |j                  fS )uF   detector CLI를 임시 repo에서 실행. (exit_code, stdout, stderr).r!   zmemory_violation_detector.pyr#   r&   Tr'   )
r#   r+   r,   r-   r.   r   r   r0   stdoutr1   )r
   argsclir*   r4   s        r   _run_detectorrW   ~   sy    
9
$'E
EC
**//
CIC^^	CH$t$F fmmV]]::r   c                f    | dz  dz  }|j                  dd       |dz  j                  |d       y)	u0   memory/specs/memory-violation-rules.yaml 작성.r   specsTparentsexist_okzmemory-violation-rules.yamlr   r   N)r   r   )r
   
rules_yamlspec_dirs      r   _seed_rulesr_      s9    h(HNN4$N/--99*w9Wr   c                ^   |D ]U  \  }}| |z  }|j                   j                  dd       |j                  |d       t        j                  dd|g| d       W t        j                  ddd	d
d|g| d       t        j                  g d| ddd      j
                  j                         }|S )u*   파일 작성 + 커밋. commit SHA 반환.TrZ   r   r   r   r;   r   commitr   z--no-verifyz-m)r   z	rev-parseHEAD)r   r(   r)   r   )parentr   r   r   r   rT   strip)r
   msgfilespathcontentfullshas          r   _commitrk      s     Cgd{$6'2ud+TB	C
 NN	$tS9
 ..$$t$VZfUUW  Jr   c                  .    e Zd ZdZd Zd Zd Zd Zd Zy)TestFix2ViolationDetectora)  version: "1.0"
rules:
  - id: rule-A
    name: "Forbidden import"
    target: "changed_files"
    file_pattern: "*.py"
    pattern_regex: "^import forbidden_module"
    severity: high
    description: "Forbidden module import"
  - id: rule-B
    name: "Bad commit phrase"
    target: "commit_messages"
    pattern_regex: "BADWORD"
    severity: high
    description: "Bad commit phrase"
  - id: rule-C
    name: "MC pending"
    target: "log_entries"
    log_field: "pending"
    expected_value: false
    severity: medium
    description: "MC pending"
c                    t        |      }t        || j                         t        |ddg      }t	        |d|g      \  }}}|dk(  sJ d|v sJ y)u    위반 없는 commit → exit 0.zclean: add module)ok.pyz
import os
--commitr   PASSNr   r_   
RULES_YAMLrk   rW   )r>   r   r
   rj   r@   rT   rE   s          r   test_clean_commit_passesz2TestFix2ViolationDetector.test_clean_commit_passes   s^    (#D$//*d/2J1KL'z3.?@faqyyr   c                    t        |      }t        || j                         t        |ddg      }t	        |d|g      \  }}}|dk(  sJ d|v sJ y)u3   changed_files 룰 위반 → exit 1, rule-A 보고.z	feat: add)zbad.pyimport forbidden_module
rp   r<   rule-ANrr   r>   r   r
   rj   r@   rE   r1   s          r   test_changed_files_violationz6TestFix2ViolationDetector.test_changed_files_violation   sb    (#D$//*+ GH
 (z3.?@aqyy6!!!r   c                    t        |      }t        || j                         t        |ddg      }t	        |d|g      \  }}}|dk(  sJ d|v sJ y)u5   commit_messages 룰 위반 → exit 1, rule-B 보고.zfix: BADWORD merged)ro   zx = 1
rp   r<   zrule-BNrr   rx   s          r   test_commit_message_violationz7TestFix2ViolationDetector.test_commit_message_violation   s^    (#D$//*d14H3IJ'z3.?@aqyy6!!!r   c           	         t        |      }t        || j                         |dz  dz  }|j                  t	        j
                  dddddgi      d	       t        |d
dg      \  }}}|dk(  sJ d|v sJ y)u2   log_entries 룰: pending=True인 entry → exit 1.r   memory-check-log.jsoncheckszMC-0001task-XT)mc_idtask_idpendingr   r   z	--task-idr<   zrule-CN)r   r_   rs   r   jsondumpsrW   )r>   r   r
   log_filer@   rE   r1   s          r   test_log_entries_violationz4TestFix2ViolationDetector.test_log_entries_violation   s    (#D$//*(?%<<JJ%.'/'+
  	 	
 ({H.EFaqyy6!!!r   c                   t        |      }t        || j                         t        |ddg       |dz  }|j	                  dd       t        j                  g d|d	       t        |d
g      \  }}}|dk(  sJ d|v sJ y)u   --staged 모드 동작.r   )zseed.txtxevil.pyrv   r   r   )r   r;   r   Tr   z--stagedr<   rw   N)r   r_   rs   rk   r   r   r   rW   )r>   r   r
   badr@   rE   r1   s          r   test_staged_modez*TestFix2ViolationDetector.test_staged_mode   s    (#D$//*f012Y2WE0d$G'zl;aqyy6!!!r   N)	rO   rP   rQ   rs   rt   ry   r{   r   r   rR   r   r   rm   rm      s"    J0	 "	""2"r   rm   c                r    | dz  }| dz  }|j                  dd       | dz  }|j                          |||dS )u   memory_check 모듈의 기본 경로를 tmp_path로 격리.

    feedback_dir는 비어있는 디렉토리로 두어 매칭 0건 보장.
    r}   r   uA   # WS
★ 항목 1: 절대 X 금지
★ 항목 2: 항상 Y 수행
r   r   anu_feedback)log_pathmemory_pathfeedback_dir)r   r   )r   r   	memory_mdr   s       r   isolated_logr     s_     11H;&IN   n,L  $ r   c                  6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	TestFix3MCSchemac                   t        dd|d   |d   |d   d      }|d   du sJ |d	   d
u sJ t        |d   d      5 }t        j                  |      }ddd       d   d   }|d   du sJ |d	   d
u sJ |d   J y# 1 sw Y   +xY w)u@   issue_mc 직후 pending=True, acknowledged=False, acked_at=None.r   z	test descr   r   r   Tr   r   r   _skip_anu_memoryr   acknowledgedFr   r   Nr~   acked_at)r   openr   load)r>   r   r4   fdatalasts         r   "test_issue_mc_pending_default_truez3TestFix3MCSchema.test_issue_mc_pending_default_true'  s    !*-$]3%n5!
 i D(((n%...,z*W= 	 99Q<D	 H~b!I$&&&N#u,,,J'''	  	 s   A==Bc                    t        dd|d   |d   |d   d      }t        |d   t              sJ t        |d         d	k\  sJ y
)u1   회귀 0: 평면 memory_items_read 배열 유지.ztask-Ytestr   r   r   Tr   memory_items_read   N)r   
isinstancelistlen)r>   r   r4   s      r   )test_issue_mc_memory_items_read_preservedz:TestFix3MCSchema.test_issue_mc_memory_items_read_preserved<  s^    !*-$]3%n5!
 &!45t<<<6-./1444r   c                    t        dd|d   |d   |d   d      }|d   }t        |      d	k\  sJ |D ]7  }t        g d
      j                  |j	                               sJ |d   du r7J  y)uR   memory_items_structured: memory_item_id/source_path/item_type/ack_required 포함.ztask-Zr   r   r   r   Tr   memory_items_structuredr   )memory_item_idsource_path	item_typeack_requiredr   N)r   r   setissubsetkeys)r>   r   r4   itemsits        r   test_issue_mc_structured_itemsz/TestFix3MCSchema.test_issue_mc_structured_itemsJ  s    !*-$]3%n5!
 015zQ 	.BUV__	   n%---		.r   c                D   t        dd|d   |d   |d   d      }|d   t        |d   	      }|du sJ t        |d   d
      5 }t        j                  |      }ddd       t        fdd   D              }|d   du sJ |d   du sJ |d   J y# 1 sw Y   :xY w)uD   ack_mc 호출 후 pending=False, acknowledged=True, acked_at 기록.ztask-Ar   r   r   r   Tr   r   r   r   r   Nc              3  4   K   | ]  }|d    k(  s|  yw)r   NrR   ).0er   s     r   	<genexpr>z7TestFix3MCSchema.test_ack_mc_success.<locals>.<genexpr>n  s     F1!G*2EQFs   r~   r   Fr   r   )r   r   r   r   r   next)r>   r   r4   okr   r   entryr   s          @r   test_ack_mc_successz$TestFix3MCSchema.test_ack_mc_success]  s    !*-$]3%n5!
 wEL$<=Tzz,z*W= 	 99Q<D	 FXFFY5(((^$,,,Z ,,,	  	 s   BBc                    |d   j                   j                  dd       |d   j                  dd       t        d|d         }|d	u sJ y
)u$   존재하지 않는 mc_id → False.r   TrZ   z{"checks": []}r   r   zMC-9999r   FN)rc   r   r   r   )r>   r   r   s      r   test_ack_mc_unknown_idz'TestFix3MCSchema.test_ack_mc_unknown_ids  sX     	Z ''--dT-JZ ++,<w+OIZ(@AU{{r   c                   t        dd|d   |d   |d   d      }t        dd|d   |d   |d   d      }t        |d	   |d   
       t        |d   
      }|D ch c]  }|d	   	 }}|d	   |v sJ |d	   |vsJ yc c}w )u/   get_pending_mcs: ack 안 된 entries만 반환.ztask-P1r   r   r   r   Tr   ztask-P2r   r   N)r   r   r   )r>   r   r1r2r   r   idss          r   test_get_pending_mcsz%TestFix3MCSchema.test_get_pending_mcs}  s    !*-$]3%n5!
 !*-$]3%n5!
 	r'{\*%=>!<
+CD#*+aqz++'{c!!!'{#%%% ,s   A<c                    t        dd|d   |d   |d   d      }t        d|d         }|J |d
   |d
   k(  sJ |d   du sJ y	)u6   get_mc_by_task: task_id로 가장 최근 entry 조회.ztask-Qr   r   r   r   Tr   r   Nr   r   )r   r   )r>   r   rr   s       r   test_get_mc_by_taskz$TestFix3MCSchema.test_get_mc_by_task  su    !*-$]3%n5!
 x,z2JK   W~7+++Y4'''r   N)
rO   rP   rQ   r   r   r   r   r   r   r   rR   r   r   r   r   &  s%    (*5.&-,&4(r   r   )r   r   returnr   )N)r
   r   r2   zdict[str, str] | Noner   ztuple[int, str])r
   r   rU   z	list[str]r   ztuple[int, str, str])r
   r   r]   r.   r   None)r
   r   re   r.   rf   zlist[tuple[str, str]]r   r.   ) __doc__
__future__r   r   r+   r   syspathlibr   pytest__file__resolverc   r#   rg   insertr.   utils.memory_checkr   r   r   r   r   r5   r7   rW   r_   rk   rm   fixturer   r   rR   r   r   <module>r      s   
 #  	  
  h'')0077 3~& ' ,$/ /n;X$b" b"T  *@( @(r   