
    i8                     \   d 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mZ ddlZdZdZej                   j#                  edd      Ze
j                   j'                  de       ded	ed
edefdZd	ededede	j.                  fdZd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$y)u^  
tests/dev7/test_scope_guard.py

dev7 scope-guard pytest 시나리오 5종 (task-2364)

시나리오:
1. 정상 케이스: snapshot 작성 → 정상 diff → exit 0
2. forbidden 위반: codegraph cron 케이스 → exit 1 + scope-violation.json
3. legacy 호환: snapshot 없음 + .allow-no-scope.log 마커 → exit 0
4. snapshot 없음, 마커도 없음: exit 1
5. 시스템 자동 파일 무시: diff에 memory/heartbeats/foo.json만 → exit 0

함수 단위 테스트:
- _parse_allowed_resources: yaml 파싱, inline list, 못 찾는 경우
- _save_capability_snapshot: sha256, auto forbidden 보강
    N)Pathz/home/jay/workspacez-/home/jay/workspace/.worktrees/task-2364-dev7scriptsztask-scope-guard.shcaps_dirtask_idsnapshotreturnc                     | j                  dd       | | dz  }|j                  t        j                  |      d       |S )u$   테스트용 snapshot 파일 작성.Tparentsexist_ok.jsonzutf-8)encoding)mkdir
write_textjsondumps)r   r   r   	snap_files       2/home/jay/workspace/tests/dev7/test_scope_guard.pywrite_snapshotr   &   sE    NN4$N/gYe,,IH-@    diff_contentenv_workspacec                    ddl }|j                  ddd      5 }|j                  |       |j                  }ddd       	 t        j
                  j                         }||d<   t        j                  dt        | gd	d	|
      }|t	        j                  |       S # 1 sw Y   exY w# t	        j                         w xY w)u,   task-scope-guard.sh를 subprocess로 호출.r   Nwz.txtF)modesuffixdelete	WORKSPACEbashT)capture_outputtextenv)tempfileNamedTemporaryFilewritenameosenvironcopy
subprocessrunSCOPE_GUARD_SCRIPTunlink)r   r   r   r#   f	diff_filer"   results           r   run_scope_guardr1   .   s    		$	$#fU	$	K q	FF	jjoo(K')<	
 
		)  			)s   B AB' B$'B>c           	      F   d}| dz  dz  }| dz  dz  }|j                  dd       |ddd	d
gdgg dddd}t        |||       d}t        ||t        |             }	 |j                  }d}||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|j                   d|j                   d|j                         dz   d|
iz  }t        t        j                  |            dx}x}	}d}|j                  }||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }
t        j                  d |j                         dz   d|
iz  }t        t        j                  |            dx}x}}|| d!z  }|j!                         r|j#                          yy# || d!z  }|j!                         r|j#                          w w xY w)"uF   정상 케이스: snapshot 있고 diff 파일이 scope 내 → exit 0.ztest-sg-scenario1memorycapabilitieseventsTr
   2026-05-02T17:00:00deadbeefscripts/finish-task.sh%memory/plans/bot-capability-system/**memory/events/*.cron-*manual0   pathsforbidden_pathscommandsmerge_policy	ttl_hoursr   captured_atsource_sha256allowed_resourceszBscripts/finish-task.sh
memory/plans/bot-capability-system/plan.md
r   ==z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sr0   py0py2py5   exit 0 기대, got 
stdout=
stderr=
>assert %(py7)spy7NPASSinz.%(py1)s in %(py5)s
{%(py5)s = %(py3)s.stdout
}py1py3rM      PASS 메시지 기대
stdout=r   r   r   r1   str
returncode
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgstdoutstderrAssertionError_format_explanationexistsr-   )tmp_pathr   r   
events_dirr   r   r0   @py_assert1@py_assert4@py_assert3@py_format6@py_format8@py_assert0@py_assert2r   s                  r   test_scenario1_passrs   F   s}   !G("^3HH$x/JTD1 ,#.0WX 89$
	H 8Wh/YLWlCMBF    	AA  	A A%  	A  	A  	A A  	A  	A  	A  	A  	A  	Av  	A  	A  	Av  	A  	A  	A   	A  	A  	AA  	A  	A  	A)<V=N=N<OyY_YfYfXggpqwq~q~p  (A  	A  	A  	A  	A  	A  	A  	AXXv&XXXvXXXvXXXXXXXXXXXXXXX*H(XXXXXXXX '%00	  '%00	 s   G/I5 5+J c           	      t
   d}| dz  dz  }| dz  dz  }|j                  dd       |ddd	gd
gg dddd}t        |||       d}t        ||t        |             }|| dz  }	 |j                  }d}	||	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|j                   d|j                   d|j                         dz   d|iz  }t        t        j                  |            dx}x}
}	|j                   } |       }
|
st        j                  d|       dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |
      dz  }t        t        j                  |            dx}}
t#        |      5 }t%        j&                  |      }ddd       d    }||k(  }|st        j                  d|fd!||f      t        j                  |      d t        j                         v st        j                  |      rt        j                  |      nd d"z  }d#d$|iz  }t        t        j                  |            dx}}|d%   }t)        |      }
d&}|
|kD  }|st        j                  d'|fd(|
|f      d)t        j                         v st        j                  t(              rt        j                  t(              nd)t        j                  |      t        j                  |
      t        j                  |      d*z  }d+d,|iz  }t        t        j                  |            dx}x}
x}}d- |d%   D        }t+        |      }
|
sd.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}}
|j!                         r|j-                          || d0z  }|j!                         r|j-                          yy# 1 sw Y   xY w# |j!                         r|j-                          || d0z  }|j!                         r|j-                          w w xY w)1uL   forbidden 위반: scope 밖 파일 수정 → exit 1 + scope-violation.json.ztest-sg-scenario2r3   r4   r5   Tr
   r6   r7   r8   r:   r;   r<   r=   rC   z!memory/events/cron-CC712188.json
z.scope-violation.json   rG   rI   r0   rJ      exit 1 기대, got rO   rP   rQ   rR   Nu   scope-violation.json 없음: C
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}violation_filerK   rL   py4r   z%(py1)s == %(py3)srX   rY   assert %(py5)srM   
violationsr   )>)z/%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} > %(py7)slen)rK   rL   rz   rR   zassert %(py9)spy9c              3   *   K   | ]  }d |d   v   yw)zcron-CC712188.jsonpathN ).0vs     r   	<genexpr>z5test_scenario2_forbidden_violation.<locals>.<genexpr>   s     R'1V94Rs   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyr   )r   r   r1   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   openr   loadr   r   r-   )rj   r   r   rk   r   r   r0   rx   rl   rm   rn   ro   rp   @py_format5r.   vdatarq   rr   @py_format4@py_assert6@py_assert5@py_format10r   s                          r   "test_scenario2_forbidden_violationr   l   s"   !G("^3HH$x/JTD1 ,#./ 89$
	H 8Wh/ 8LWlCMBFWI-B"CCN    	AA  	A A%  	A  	A  	A A  	A  	A  	A  	A  	A  	Av  	A  	A  	Av  	A  	A  	A   	A  	A  	AA  	A  	A  	A)<V=N=N<OyY_YfYfXggpqwq~q~p  (A  	A  	A  	A  	A  	A  	A  	A$$X$&X&XX*GGW(XXXXXXX~XXX~XXX$XXX&XXXXXX.! 	!QIIaLE	!Y*7****7*********7***7*******&+s&'+!+'!++++'!++++++s+++s+++&+++'+++!+++++++ReL>QRRsRRRRRRRRRsRRRsRRRRRRRRRRRRRR  "!!#'%00	 	! 	!   "!!#'%00	 s'   #GS, 2SIS, S)$S, ,AT7c                 X   d}| dz  dz  }|j                  dd       | dz  dz  j                  dd       || dz  }|j                  t        j                  |dd	             d
}t	        ||t        |             }	 |j                  }d}||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|j                   d|j                   d|j                         dz   d|	iz  }
t!        t        j"                  |
            dx}x}}g }d}|j                  }|j$                  } |       }||v }|}|s'd}|j                  }|j$                  } |       }||v }|}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }|j'                  |       |st        j                  dfdf      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                        t        j                        t        j                  |      dz  }dd |iz  }|j'                  |       t        j(                  |d!      i z  }t        j                  d"|j                         d#z   d$|iz  }t!        t        j"                  |            dx}x}x}x}x}x}x}x}x}x}x}}|j+                         r|j-                          yy# |j+                         r|j-                          w w xY w)%uI   legacy 호환: snapshot 없음 + .allow-no-scope.log → exit 0 + 경고.ztest-sg-scenario3r3   r5   Tr
   r4   z.allow-no-scope.logtest)r   reasonscripts/finish-task.sh
r   rG   rI   r0   rJ   rN   rO   rP   rQ   rR   Nlegacyzallow-no-scoperT   zb%(py3)s in %(py11)s
{%(py11)s = %(py9)s
{%(py9)s = %(py7)s
{%(py7)s = %(py5)s.stderr
}.lower
}()
}rY   rM   rR   r   py11%(py13)spy13zh%(py16)s in %(py24)s
{%(py24)s = %(py22)s
{%(py22)s = %(py20)s
{%(py20)s = %(py18)s.stderr
}.lower
}()
}py16py18py20py22py24%(py26)spy26ru   u&   legacy 경고 메시지 없음
stderr=
>assert %(py29)spy29)r   r   r   r   r1   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   lowerappend_format_boolopri   r-   )rj   r   rk   marker_filer   r0   rl   rm   rn   ro   rp   rr   r   @py_assert8@py_assert10rq   @py_assert15@py_assert19@py_assert21@py_assert23@py_assert17@py_format12@py_format14@py_format25@py_format27@py_format28@py_format30s                              r   $test_scenario3_legacy_allow_no_scoper      s\   !GH$x/JTD1>)000M '*=>>K4::'V&LMN-LWlCMBF!    	AA  	A A%  	A  	A  	A A  	A  	A  	A  	A  	A  	Av  	A  	A  	Av  	A  	A  	A   	A  	A  	AA  	A  	A  	A)<V=N=N<OyY_YfYfXggpqwq~q~p  (A  	A  	A  	A  	A  	A  	A  	A	Fx 	F6== 	F=.. 	F.0 	Fx00 	F4D 	F 	FH[H[ 	FH[H] 	F4DH]4] 	F 	F4E4E	Fx0 	F 	F<EI  	F 	F?Ev	F 	F-E-E " 	F 	F<EI " 	F 	F<EI ) 	F 	F<EI / 	F 	F<EI 1 	F 	F 	F?Ev	F?E	F4E4E	F4DH] 	F 	F<EI 5E 	F 	F?Ev	F 	F-E-E IO 	F 	F<EI IO 	F 	F<EI IV 	F 	F<EI I\ 	F 	F<EI I^ 	F 	F 	F?Ev	F?E	F7E~	F 	F4E4E5fmm_E	F 	F 	F2E2E	F 	F 	F 	F 	F    ;   s   ?M%P #P)c                 f   d}| dz  dz  j                  dd       | dz  dz  j                  dd       d}t        ||t        |             }|j                  }d}||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|j                   d|j                   d|j                         dz   d|iz  }t        t	        j                  |            dx}x}}g }d}	|j                  }
|
j                  } |       }|	|v }|}|s'd}|j                  }|j                  } |       }||v }|}|st	        j
                  d|fd|	|f      t	        j                  |	      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |
      t	        j                  |      t	        j                  |      dz  }dd|iz  }|j!                  |       |st	        j
                  dfdf      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                        t	        j                        t	        j                  |      dz  }dd|iz  }|j!                  |       t	        j"                  |d      i z  }t	        j                  d|j                         dz   d |iz  }t        t	        j                  |            dx}x}x}	x}x}
x}x}x}x}x}x}}y)!uA   snapshot 없음 + 마커도 없음 → exit 1 + 에러 메시지.ztest-sg-scenario4r3   r4   Tr
   r5   r   ru   rG   rI   r0   rJ   rv   rO   rP   rQ   rR   Nr   dispatchrT   r   r   r   r   r   r   r   r   u   에러 메시지 없음
stderr=r   r   )r   r1   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   r   r   r   )rj   r   r   r0   rl   rm   rn   ro   rp   rr   r   r   r   rq   r   r   r   r   r   r   r   r   r   r   r   s                            r   $test_scenario4_no_snapshot_no_markerr      sF   !G>)000M8#**4$*G-LWlCMBF||!|||||||||6|||6|||||||||%89J9J8K9U[UbUbTcclmsmzmzl{#||||||||;: ; ;,, ;,. ;:.. ;* ; ;@S@S ;@S@U ;*@U2U ; ;):):;:. ; ;1:  ; ;4:F; ;":":   ; ;1:   ; ;1: ' ; ;1: - ; ;1: / ; ; ;4:F;4:;):):;*@U ; ;1: 3= ; ;4:F; ;":": AG ; ;1: AG ; ;1: AN ; ;1: AT ; ;1: AV ; ; ;4:F;4:;,:N; ;):):
*6==/:; ; ;':':; ; ; ; ;r   c           	      2   d}| dz  dz  }| dz  dz  }|j                  dd       |ddd	gg g d
ddd}t        |||       d}t        ||t        |             }|| dz  }	 |j                  }d}	||	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|j                   d|j                   d|j                         dz   d|iz  }t        t        j                  |            dx}x}
}	d}|j                  }	||	v }|st        j                  d|fd||	f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |	      dz  }t        j                  d|j                         dz   d|iz  }t        t        j                  |            dx}x}}	|j!                         r|j#                          yy# |j!                         r|j#                          w w xY w) uB   시스템 자동 파일(memory/heartbeats/...)만 diff → exit 0.ztest-sg-scenario5r3   r4   r5   Tr
   r6   r7   r8   r;   r<   r=   rC   zememory/heartbeats/foo.json
memory/daily/2026-05-02.md
bot-activity.json
token-ledger.json
.heartbeat
r   r   rG   rI   r0   rJ   rN   rO   rP   rQ   rR   NrS   rT   rV   rW   rZ   r[   )rj   r   r   rk   r   r   r0   r   rl   rm   rn   ro   rp   rq   rr   s                  r   #test_scenario5_system_files_ignoredr      sh   !G("^3HH$x/JTD1 ,#./!$
	H 8Wh/	  WlCMBFgYe,,I    	AA  	A A%  	A  	A  	A A  	A  	A  	A  	A  	A  	Av  	A  	A  	Av  	A  	A  	A   	A  	A  	AA  	A  	A  	A)<V=N=N<OyY_YfYfXggpqwq~q~p  (A  	A  	A  	A  	A  	A  	A  	AXXv&XXXvXXXvXXXXXXXXXXXXXXX*H(XXXXXXXX 9 s   "G/I3 3#Jc                     ddl m}  d} | |      }d}||u}|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
z   d|iz  }t        t        j                  |            dx}}d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}y)u2   fenced yaml 블록에서 allowed_resources 파싱.r   _parse_allowed_resourcesa  
# task
## allowed_resources
```yaml
allowed_resources:
  paths:
    - "scripts/finish-task.sh"
    - "memory/plans/bot-capability-system/**"
  forbidden_paths:
    - "memory/events/*.cron-*"
  commands:
    - "pytest"
  merge_policy: "manual"
  ttl_hours: 48
```
Nis notz%(py0)s is not %(py3)srrK   rY   u"   파싱 결과가 None이면 안됨
>assert %(py5)srM   r8   r>   rT   z%(py1)s in %(py4)srX   rz   assert %(py6)spy6r9   r:   r?   rA   r;   rG   )z%(py1)s == %(py4)srB   r<   r   r   r^   r_   r`   ra   rb   rc   rd   rg   rh   r   r!   r   rr   rl   r   ro   rq   rn   r   @py_format7s              r   'test_parse_allowed_resources_yaml_blockr      s   1D  	!&A>1D=>>>1D>>>>>>1>>>1>>>D>>>>>>>>>>#1qz1#z1111#z111#111z11111112@aj@2j@@@@2j@@@2@@@j@@@@@@@#;q):';;#';;;;;#';;;;#;;;';;;;;;;;^((((((((((((((((((([>R>R>R>Rr   c                  h   ddl m}  d} | |      }d}||u}|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}}d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}y)u"   인라인 리스트 형식 파싱.r   r   z
```yaml
allowed_resources:
  paths: [foo.py, bar.py]
  forbidden_paths: [secrets/**]
  merge_policy: manual
  ttl_hours: 24
```
Nr   r   r   r   r}   rM   zfoo.pyr>   rT   r   r   r   r   zbar.py
secrets/**r?   )
r   r   r^   r_   r`   ra   rb   rc   rg   rh   r   s              r   (test_parse_allowed_resources_inline_listr     s_   1D 	!&A1D=1D11D!qz!8z!!!!8z!!!8!!!z!!!!!!!!qz!8z!!!!8z!!!8!!!z!!!!!!!/1.//</////<////<///////////r   c                     ddl m}  d} | |      }d}||u }|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
z   d|iz  }t        t        j                  |            dx}}y)u,   allowed_resources 없는 경우 None 반환.r   r   u1   # 단순 task 설명
어떤 작업을 합니다.
Nisz%(py0)s is %(py3)sr   r      None 기대, got r   rM   r   r   r!   r   rr   rl   r   ro   s          r   &test_parse_allowed_resources_not_foundr   (  s|    1@D &A-19---1------1---1------)!-------r   c                     ddl m}  d} | |      }d}||u }|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
z   d|iz  }t        t        j                  |            dx}}y)u>   yaml 블록이 있어도 allowed_resources 키 없으면 None.r   r   z#
```yaml
other_key:
  foo: bar
```
Nr   r   r   r   r   r   rM   r   r   s          r   -test_parse_allowed_resources_yaml_without_keyr   1  s    1D 	!&A-19---1------1---1------)!-------r   c                     ddl m}  d}dgg g ddd}d} | |||      }	 |j                  } |       }|st        j                  d	|       d
z   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}t        |      5 }t        j                  |      }	ddd       	d   }
|
|k(  }|st        j                  d|fd|
|f      t        j                  |
      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}
}|	d   }
|
sNt        j                  d      dz   dt        j                  |
      iz  }t        t        j                  |            d}
ddl}|j!                  |j#                               j%                         }|	d   }
|
|k(  }|st        j                  d|fd|
|f      t        j                  |
      dt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                  d|	d    d|       dz   d|iz  }t        t        j                  |            dx}
}|j                         r|j'                          yy# 1 sw Y   %xY w# |j                         r|j'                          w w xY w)u'   기본 snapshot 저장 + sha256 확인.r   _save_capability_snapshotztask-test-snap-basicr8   r;      r=   zhello world snapshot testu   snapshot 파일 없음: rw   	snap_pathry   Nr   rG   r{   r|   r}   rM   rE   u   sha256 비어있음z
>assert %(py1)srX   expectedu   sha256 불일치: z != r   )r   r   ri   r^   rd   r`   ra   rb   rc   rg   rh   r   r   r   r_   hashlibsha256encode	hexdigestr-   )r   r   arsource_textr   rl   rn   r   r.   datarq   rr   r   ro   @py_format2r   r   s                    r   #test_save_capability_snapshot_basicr   C  sK   2$G*+ 
B .K)'2{CII!I!II%=i[#IIIIIIIyIIIyIIIIII!IIIIII)_ 	 99Q<D	 I)'))))')))))))))')))')))))))O$;$;;&;;;;$;;;;;>>+"4"4"67AACO$l$0lll$lll$lllllllllllll4FtOG\F]]abjak2lllllll 	  	   s%   C
L/ )L"?HL/ "L,'L/ /#Mc                  @   ddl m}  d}dgdgg ddd} | ||d	      }	 t        |      5 }t        j                  |      }d
d
d
       d   d   }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }	t        j                  d|       dz   d|	iz  }
t        t        j                  |
            d
x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }	t        j                  d|       dz   d|	iz  }
t        t        j                  |
            d
x}}|j                         r|j                          y
y
# 1 sw Y   xY w# |j                         r|j                          w w xY w)u,   memory/capabilities/** 자동 보강 확인.r   r   ztask-test-snap-forbiddenr8   r   r;   r   r=   test sourceNrF   r?   memory/capabilities/**rT   )z%(py1)s in %(py3)s	forbiddenr|   u-   memory/capabilities/** 자동 보강 없음: r   rM   u&   기존 forbidden_paths 유지 안됨: )r   r   r   r   r   r^   r_   rc   r`   ra   rb   rd   rg   rh   ri   r-   )r   r   r   r   r.   r   r   rq   rr   r   ro   s              r   9test_save_capability_snapshot_auto_forbidden_capabilitiesr   a  s+   2(G*+(> 
B *'2}EI
)_ 	 99Q<D	 ,-.?@	' 	H'94 	H6G6G	H'9 	H 	H>Gi ( 	H 	HAG	H 	H/G/G ,5 	H 	H>Gi ,5 	H 	H6G6G;I;G	H 	H 	H4G4G	H 	H 	A|y( 	A/@/@	A|y 	A 	A7@y  	A 	A:@&	A 	A(@(@  ) 	A 	A7@y  ) 	A 	A/@/@4YK@	A 	A 	A-@-@	A 	A  	  	   s"   G: G-FG: -G72G: :#Hc                     ddl m}  d}dgdgg ddd} | ||d	      }	 t        |      5 }t        j                  |      }d
d
d
       d   d   }|j                  d      }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z   d|
iz  }t        t        j                  |            d
x}	}|j                         r|j!                          y
y
# 1 sw Y   xY w# |j                         r|j!                          w w xY w)uA   이미 memory/capabilities/**가 있으면 중복 추가 안 함.r   r   ztask-test-snap-nodupr8   r   r;   r   r=   r   NrF   r?   ru   rG   )z%(py0)s == %(py3)scountr   u   중복 추가됨: r   rM   )r   r   r   r   r   r   r^   r_   r`   ra   rb   rc   rd   rg   rh   ri   r-   )r   r   r   r   r.   r   r   r   rr   rl   r   ro   s               r   4test_save_capability_snapshot_no_duplicate_forbiddenr   |  s+   2$G*+45 
B *'2}EI)_ 	 99Q<D	 ,-.?@	 89;uz;;;u;;;;;;u;;;u;;;;;;/	{;;;;;;; 	  	   s"   E EC E EE #E1)%__doc__builtinsr`   _pytest.assertion.rewrite	assertionrewriter^   r   r'   r*   syspathlibr   pytestWORKSPACE_ROOTWORKTREE_ROOTr   joinr,   insertr\   dictr   CompletedProcessr1   rs   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s   "   	  
   '?WW\\-<QR  = !T C 4 D S  C JLgLg 0L(^!:;&%X :0(..$<6r   