
    (<i\=              
       @   U d 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d            Z	 e
e	      ej                  vr"ej                  j                  d e
e	             ddlmZ ddddd	gd
dddddddgdgdZeed<   dddddiiZeed<   d'dededz  defdZd'dededz  defdZdej*                  dedeeef   fdZdedej*                  ddfdZdedej*                  ddfdZdedej*                  ddfdZdedej*                  ddfd Zdedej*                  ddfd!Zdedej*                  ddfd"Zdedej*                  ddfd#Zdedej*                  ddfd$Zdedej*                  ddfd%Z dedej*                  ddfd&Z!y)(u  test_todo_sync.py

task-637.1 TDD RED Phase — utils/todo_sync.py 단위 테스트 (아르고스 작성)

테스트 항목:
1. test_sync_task_completion_match: sub_item.task_id 매칭 → done=True
2. test_sync_task_completion_no_match: 매칭 없음 → 변경 없음
3. test_sync_task_completion_already_done: 이미 done=True → 변경 없음
4. test_sync_issue_all_done: 모든 sub_items done → issue.status="done" + completed_at 기록
5. test_retroactive_sync: 다건 completed 태스크 일괄 동기화
6. test_link_task_to_issue: 수동 task_id ↔ issue 연결
7. test_link_task_to_issue_with_sub_item_title: sub_item_title 지정 연결
8. test_backup_created: todo.json 수정 전 .bak 파일 생성
9. test_no_reverse_done: done=True → done=False 되돌리기 불가 (단방향)
10. test_linked_tasks_match: issue.linked_tasks에 task_id 포함 시 매칭

격리: tmp_path + monkeypatch 로 TODO_FILE / TIMERS_FILE 경로 오버라이드
    N)PathWORKSPACE_ROOTz/home/jay/workspace1.0	issue-007pending
task-434.1   Phase 0: 환경 셋업Ftitledonetask_idzPhase 1 POC
task-500.1idstatuscompleted_atlinked_tasks	sub_itemsversionissues_TODO_TEMPLATEtasks	completedr   r   _TIMERS_TEMPLATEtmp_pathdatareturnc                     | dz  }|j                  dd       |dz  }|j                  t        j                  |xs t        d      d       |S )	u<   tmp_path/memory/todo.json 을 생성하고 경로를 반환.memoryTparentsexist_okz	todo.jsonFensure_asciiutf-8encoding)mkdir
write_textjsondumpsr   )r   r   mem	todo_files       E/home/jay/workspace/.worktrees/task-2057-dev2/tests/test_todo_sync.py_write_todor1   G   sP    
X
CIIdTI*k!ID$:NOZab    c                     | dz  }|j                  dd       |dz  }|j                  t        j                  |xs t        d      d       |S )	uC   tmp_path/memory/task-timers.json 을 생성하고 경로를 반환.r!   Tr"   task-timers.jsonFr%   r'   r(   )r*   r+   r,   r-   r   )r   r   r.   timers_files       r0   _write_timersr6   P   sR    
X
CIIdTI***K4::d&>.>US^efr2   monkeypatchc                     t        |      }t        |      }| j                  t        d|       | j                  t        d|       ||fS )uM   todo_sync 모듈의 TODO_FILE / TIMERS_FILE 을 tmp_path 기반으로 패치.	TODO_FILETIMERS_FILE)r1   r6   setattr	todo_sync)r7   r   r/   r5   s       r0   _patch_pathsr=   Y   sE    H%I)K	;	:	=+>k!!r2   c                 ^   t        ||       \  }}t        j                  d      }t        |t              sJ d       |d   dk(  sJ d       t        |d         dk\  sJ d       t        j                  |j                  d	            }|d
   d   d   d   }|d   dk(  sJ |d   du sJ d       y)uC   sub_item에 task_id가 있고 해당 task_id로 sync → done=True.r      반환값은 dict이어야 함updated   u0   한 개의 sub_item이 업데이트되어야 함detailsu,   details 리스트에 항목이 있어야 함r'   r(   r   r   r   r   r   Tu+   Phase 1 POC sub_item이 done=True여야 함N)	r=   r<   sync_task_completion
isinstancedictlenr,   loads	read_text)r   r7   r/   _resultsavedphase1s          r0   test_sync_task_completion_matchrM   g   s    X6LIq++L9Ffd#E%EE#)!U#UU!vi !Q&V(VV&JJy**G*<=E8_Q,Q/F),,,&>T!P#PP!r2   c                    t        ||       \  }}|j                  d      }t        j                  d      }|d   dk(  sJ d       |j                  d      }t	        j
                  |      t	        j
                  |      k(  sJ d       y)	u:   매칭되는 sub_item이 없는 task_id → 변경 없음.r'   r(   z
task-999.9r@   r   u(   매칭 없으면 updated=0 이어야 함u%   파일 내용이 변경되면 안 됨N)r=   rH   r<   rC   r,   rG   )r   r7   r/   rI   originalrJ   rK   s          r0   "test_sync_task_completion_no_matchrP   |   s    X6LIq""G"4H++L9F)!M#MM!1E::e

8 44]6]]4r2   c           	      x   ddddg ddddgd	gd
}t        | |      }t        |        |j                  t        d|       |j                  t        d| dz  dz         t        j                  d      }|d   dk(  sJ d       t        j                  |j                  d            }|d   d   d   d   d   du sJ y)u:   이미 done=True인 sub_item → updated=0, 파일 불변.r   z	issue-010r   Nu   이미 완료Tz
task-300.1r
   r   r   r9   r:   r!   r4   r@   r   u+   이미 done=True면 updated=0 이어야 함r'   r(   r   r   r   r1   r6   r;   r<   rC   r,   rG   rH   )r   r7   already_done_todor/   rJ   rK   s         r0   &test_sync_task_completion_already_donerT      s      "# $ "-tU

 H&78I(	;	:	=(X2EHZ2Z[++L9F)!P#PP!JJy**G*<=E?1k*1-f5===r2   c           
         ddddg ddddd	d
ddgdgd}t        | |      }t        |        |j                  t        d|       |j                  t        d| dz  dz         t        j                  d      }|d   dk(  sJ t        j                  |j                  d            }|d   d   }|d   dk(  sJ d       |d   J d       y)uI   모든 sub_items가 done이면 issue.status='done' + completed_at 기록.r   z	issue-020in_progressNzStep ATz
task-100.1r
   zStep BFz
task-101.1r   r   r9   r:   r!   r4   r@   rA   r'   r(   r   r   r   r   u-   모든 sub_items done → issue.status='done'r   u#   completed_at이 기록되어야 함rR   )r   r7   one_left_todor/   rJ   rK   issues          r0   test_sync_issue_all_donerY      s      "' $ "&N&,O	
M Hm4I(	;	:	=(X2EHZ2Z[++L9F)!!!JJy**G*<=E(OAE?f$U&UU$ ,S.SS,r2   c                 H   ddddg ddddd	dd
dddddgdgd}ddddd
ddddddi}t        | |      }t        | |      }|j                  t        d|       |j                  t        d|       t        j                         }t        |t              sJ d       |d   dk(  sJ d       t        |d         dk\  sJ t        j                  |j                  d            }|d   d   d   }|d   d    d!u sJ d"       |d#   d    d!u sJ d$       |d   d    du sJ d%       y)&uM   다건 completed 태스크를 전수 스캔하여 todo.json 일괄 동기화.r   z	issue-030r   NzPhase AF
task-200.1r
   zPhase B
task-201.1zPhase Cr   r   r   r   r   
task-202.1rV   )r[   r\   r]   r9   r:   r?   total_synced   u2   완료된 태스크 2개가 동기화되어야 함rB   r'   r(   r   r   r   r   TzPhase A done=TruerA   zPhase B done=Trueu&   Phase C는 task_id 없어서 그대로)r1   r6   r;   r<   retroactive_syncrD   rE   rF   r,   rG   rH   )	r   r7   
multi_todomulti_timersr/   r5   rJ   rK   r   s	            r0   test_retroactive_syncrc      s     "# $ "'<P'<P'4H

J" 	&2kJ&2kJ&2mL
L Hj1I,7K	;	:	=+>'')Ffd#E%EE#.!Q&\(\\&vi !Q&&&JJy**G*<=Eh";/IQ<4'<)<<'Q<4'<)<<'Q<5(R*RR(r2   c                    t        ||       \  }}t        j                  dd      }t        |t              sJ |d   du sJ d       d|v sJ t        j                  |j                  d            }|d	   d
   }d|d   v sJ d       y)u@   수동으로 task_id를 issue에 연결: linked_tasks에 추가.z
task-600.1r   linkedTu   linked=True 이어야 함messager'   r(   r   r   r   u#   linked_tasks에 추가되어야 함N)r=   r<   link_task_to_issuerD   rE   r,   rG   rH   )r   r7   r/   rI   rJ   rK   rX   s          r0   test_link_task_to_issuerh     s    X6LIq)),DFfd###(t#@%@@#JJy**G*<=E(OAE500W2WW0r2   c                    t        ||       \  }}t        j                  ddd      }|d   du sJ t        j                  |j                  d            }|d	   d
   }d|d   v sJ t        d |d   D              }|d   dk(  sJ d       y)u?   sub_item_title 지정 시 해당 sub_item.task_id에도 연결.z
task-601.1r   r	   )sub_item_titlere   Tr'   r(   r   r   r   c              3   2   K   | ]  }|d    dk(  s|  yw)r   r	   N ).0ss     r0   	<genexpr>z>test_link_task_to_issue_with_sub_item_title.<locals>.<genexpr>)  s     Z1W:AY3Y!Zs   r   r   u'   sub_item.task_id가 설정되어야 함N)r=   r<   rg   r,   rG   rH   next)r   r7   r/   rI   rJ   rK   rX   phase0s           r0   +test_link_task_to_issue_with_sub_item_titlerr     s    X6LIq))/F (t###JJy**G*<=E(OAE50000ZU;/ZZF),W.WW,r2   c                 0   t        ||       \  }}t        j                  d       |j                  |j                  dz   z  }|j                         sJ d       t        j                  |j                  d            d   }|d   d   d	   d
   du sJ d       y)u/   todo.json 수정 전 .bak 파일 생성 확인.r   z.baku+   todo.json.bak 파일이 생성되어야 함r'   r(   r   r   r   rA   r   Fu%   백업은 수정 전 상태여야 함N)	r=   r<   rC   parentnameexistsr,   rG   rH   )r   r7   r/   rI   bak_fileoriginal_issuess         r0   test_backup_createdry   2  s    X6LIq""<09>>F#:;H??KKKjj!3!3W!3!EFxPO1k*1-f5>g@gg>r2   c           	         dddddgddddgd	gd
}t        | |      }t        |        |j                  t        d|       |j                  t        d| dz  dz         t        j                  d       t        j                  |j                  d            }|d   d   d   d   d   du sJ d       |d   d   d   dk(  sJ d       y)u@   done=True → done=False 되돌리기 불가 (단방향 보장).r   z	issue-040r   z2026-03-10T10:00:00z
task-400.1u   완료된 항목Tr
   r   r   r9   r:   r!   r4   r'   r(   r   r   r   u(   done=True는 되돌릴 수 없어야 함r   u$   issue.status도 되돌리면 안 됨NrR   )r   r7   all_done_todor/   rK   s        r0   test_no_reverse_doner|   D  s      "  5!-0$<X

M Hm4I(	;	:	=(X2EHZ2Z[ ""<0JJy**G*<=E?1k*1-f5=i?ii=?1h'61Y3YY1r2   c           	         dddddgddddgd	gd
}t        | |      }t        |        |j                  t        d|       |j                  t        d| dz  dz         t        j                  d      }|d   dk\  st        |d         dk\  sJ d       t        j                  |j                  d            }|d   d   d   d   }|d   du sJ d       y)uK   issue.linked_tasks에 task_id 포함 시 sub_items 없어도 매칭 처리.r   z	issue-050r   Nr   u   연결된 태스크 작업Fr
   r   r   r9   r:   r!   r4   r@   rA   rB   uK   linked_tasks 매칭 시 업데이트 또는 details 기록이 있어야 함r'   r(   r   r   r   r   Tu4   linked_tasks 매칭 시 sub_item done=True여야 함)	r1   r6   r;   r<   rC   rF   r,   rG   rH   )r   r7   linked_todor/   rJ   rK   subs          r0   test_linked_tasks_matchr   f  s     "# $!- ;EVZ[	
K Hk2I(	;	:	=(X2EHZ2Z[++L9F 	yQ#fY&7"8A"=UTU= JJy**G*<=E
/!
[
)!
,Cv;$V VVr2   )N)"__doc__r,   ossyspathlibr   pytestenvironget
_WORKSPACEstrpathinsertutils.todo_syncr<   r   rE   __annotations__r   r1   r6   MonkeyPatchtupler=   rM   rP   rT   rY   rc   rh   rr   ry   r|   r   rl   r2   r0   <module>r      s  &  	 
   "**..!13HIJ
z?#(("HHOOAs:' $   )N2EdS'<P		
 " #!
 $ $ dTk T D t t "f00 "D "U4QU:EV "Qd QASAS QX\ Q*
^ 
^FDVDV 
^[_ 
^$>T >HZHZ >_c >BTt T&:L:L TQU TJ(SD (Sv7I7I (Sd (S`Xd X9K9K XPT X(X$ XVM_M_ Xdh X4
h$ 
hV5G5G 
hD 
h$Z4 Zf6H6H ZT ZDWd W9K9K WPT Wr2   