
     jR                       d Z ddlmZ ddlZddlmZ ddlZ ee      j                         j                  j                  j                  Z
 ee
      ej                  v r!ej                  j                   ee
             ej                  j                  d ee
             ddlmZmZmZmZmZmZmZ ddlmZmZmZmZmZ ddlmZmZm Z m!Z!m"Z" dZ#d	Z$dd
Z%ejL                  dd       Z'd Z(d Z)ddZ*ejV                  jY                  dg d      dd       Z-ejV                  jY                  dg d      	 	 	 	 dd       Z.ddZ/d Z0d Z1d Z2d Z3y)u  tests/regression/test_auto_finalize_chain_default_2529.py

회귀 테스트 — task-2529 auto finalize chain default (시스템 결함 fix).

회장 §명시 (2026-05-10):
  봇이 본질 작업과 자체 검증을 완료하면, 회장이 별도로 말하지 않아도 자동으로
  commit → push → PR → CI/Gemini → bot identity merge → smoke → reconcile까지
  진입한다. 명시적 opt-out이 없는 모든 code task는 자동 finalize chain을
  기본값으로 가진다.

회장 §명시 5 회귀 (정확히 5건):
  1. task-2524+1 사례 박제 — 자체 검증 PASS 후 PR 미생성 →
     lifecycle stuck SELF_VERIFIED_BUT_NOT_FINALIZED 자동 분류
  1-b. task-2528 사례 박제 (task-2529+1 보강, 2026-05-10) — 자체 검증 PASS 후
       commit/push/PR 미진입 → lifecycle stuck CODE_DONE_BUT_NO_COMMIT /
       SELF_VERIFIED_BUT_NOT_FINALIZED 자동 분류
  2. task md에 12단계 누락 → wrapper가 footer 자동 삽입
  3. read_only task → finalize 생략
  4. report_only task → finalize 생략
  5. code task → finalize 자동 진입 (footer 삽입 + lifecycle 정상)

본 사건 fixture (회장 §1 / §6 사례):
  - task-2524+1 (dev5 사라스와티, 2026-05-10) — 회귀/구현 PASS 후 PR 미생성
  - task-2528  (dev1 헤르메스, 2026-05-10)   — 자체 검증 PASS 후 커밋/푸시 미진입
                                                ("커밋/푸시는 별도 회장 명령 시 진행하겠습니다")

테스트 카운트 메모 (task-2529+1 정정, 2026-05-10):
  - def test_ 함수: 10개 (task-2528 fixture 추가 후)
  - parametrize 전개 후 실제 pytest collect 카운트: 15개
  - 계산: def 10 + test_regression_3(3 cases - 1) + test_regression_4(4 cases - 1) = 15
  - 봇 보고 기준 task-2529 시점 14는 def 9 + (3-1) + (4-1) = 14 — parametrize collapse가
    아니라 실제 실행 카운트로 일관됐음. 봇 보고 9건은 def test_ 함수 수, 14건은 collect 카운트.
    )annotationsN)Path)AUTO_FINALIZE_FOOTER_MARKERAUTO_FINALIZE_OPT_OUT_TOKENSDispatchStatusauto_inject_finalize_footeris_finalize_opt_outsafe_cron_dispatch"should_auto_inject_finalize_footer)TASK_KIND_BOTTASK_KIND_FOLLOWUP_ROTASK_KIND_HUMAN_RESPONSETASK_KIND_INDEPENDENTTASK_KIND_MERGE)LifecycleEvidenceStuckReasondetect_stuck_casesdetermine_stateLifecycleState
6937032012f3e244a7f4f0d036c                     t        di ddddddddddd	dd
ddddddddddddddddddddddddddddddddddddddd}|j                  |        t        di |S )uW   LifecycleEvidence 기본값 (FINALIZED 직전 상태) → 회귀에서 필드 override.task_idz	task-9999	pr_numberNpr_statemerge_commitmerged_into_mainF	ci_statussmoke_statustimer_statustimer_end_timehas_donehas_done_ackedhas_merge_donehas_qc_resulthas_followuphas_escalate_markerescalate_marker_age_minutestelegram_reply_truncatedbot_session_statusworktree_existsbranch_pushed_to_remoteworktree_mtime_seconds_agohas_pushed_commitsreport_artifact_presentprocess_alivepr_open_age_secondsreport_artifact_age_seconds )dictupdater   )	overridesbases     M/home/jay/workspace/tests/regression/test_auto_finalize_chain_default_2529.py_make_evidencer9   R   s(      	
           "  %)!" "'#$  %& '( !&)* $(+, !-. !&/0 12 !34 %)5D8 	KK	$t$$    c                    | dz  S )u<   production audit-jsonl 오염 방지 — tmp_path에 격리.zcron-targeting-audit.jsonlr3   )tmp_paths    r8   
audit_pathr=   t   s     222r:   c                 v   t        ddddddddddd      } t        |       }|D ch c]  }|j                   }}t        j                  |v s,J d|D cg c]  }|j                  j
                   c}        t        j                  |v sJ t        |       \  }}|t        j                  k(  sJ yc c}w c c}w )u   본 사건 fixture: dev5 사라스와티가 회귀/구현 PASS 후 PR 미생성한 사례.

    재발 시 lifecycle_reconciliation_manager가 stuck으로 자동 분류해야 한다.
    ztask-2524+1T     @NF)r   r/   r2   r   r   r   r+   r-   r.   r,   r    u;   task-2524+1 본 사건이 stuck 분류되지 않음. cases=)
r9   r   reasonr   SELF_VERIFIED_BUT_NOT_FINALIZEDvalueCODE_DONE_BUT_NO_COMMITr   r   STUCK_NEEDS_RECONCILE)evidencecasescreasonsstate_s         r8   Ktest_regression_1_task_2524_plus_1_self_verified_but_no_pr_finalize_missingrK      s    
  $$)#(  %H" x(E!&'Aqxx'G' 66'A 
E_dFeZ[qxx~~FeEfgA ..'999 x(HE1N88888 ( Gfs   B1B6c                 V   t        ddddddddddd      } t        |       }|D ch c]  }|j                   }}t        j                  |v s>t        j
                  |v s,J d|D cg c]  }|j                  j                   c}        t        j
                  |v s"J d|D cg c]  }|j                   c}        t        j                  |v s"J d	|D cg c]  }|j                   c}        t        |       \  }}|t        j                  k(  sJ yc c}w c c}w c c}w c c}w )
u^  task-2528 사례 박제 — 자체 검증 PASS 후 commit/push/PR 미진입.

    회장 §6 (2026-05-10) 명시 충족: task-2524 / task-2528 사례 모두 회귀 fixture에 박제.
    회장 §명시 (2026-05-10): "lifecycle stuck enum 또는 audit log만으로 task-2528
    fixture 충족을 대체하지 않는다" → 명시 def test_ 함수로 박제.

    Source:
      - dev1 헤르메스, 2026-05-10 — 자체 검증 보고서(memory/reports/task-2528.md) 작성 후
        commit/push 단계 미진입.
      - 봇 명시 발언: "커밋/푸시는 별도 회장 명령 시 진행하겠습니다"
        (auto-finalize-chain-missing-260510.jsonl).
      - 결과: AUTO_FINALIZE_CHAIN_MISSING audit log 생성, 회장 §결정으로 task-2528+1 발행.

    재발 시 lifecycle_reconciliation_manager가 자동으로 stuck 분류해야 한다.
    z	task-2528Tr?   FN)r   r/   r2   r.   r,   r   r   r   r+   r-   r    u9   task-2528 본 사건이 stuck 분류되지 않음. cases=u[   CODE_DONE_BUT_NO_COMMIT 미분류 — task-2528은 commit 단계 미진입 사례. reasons=uk   SELF_VERIFIED_BUT_NOT_FINALIZED 미분류 — task-2528은 자체 검증 PASS 후 finalize 미완. reasons=)
r9   r   r@   r   rA   rC   rB   r   r   rD   )rE   rF   rG   rH   rrI   rJ   s          r8   Qtest_regression_1b_task_2528_dev1_hermes_self_verified_but_finalize_chain_missingrN      sT      $$) ! %#(#H( x(E!&'Aqxx'G'
 	33w>..'9*/0Q!((..01	3		: ..'9 %,-AGG-.	09 66'A %,-AGG-.	0A x(HE1N888885 ( 1 . .s   D%D#D!D&c           	        d}t         |vsJ t        |      rJ t        |dt        t        t
        d|       }|j                  t        j                  k(  sJ d|j                          t        |j                        }d|v sJ |j                  d      }||dz      }t         |v sJ d       d	D ]  }||v rJ d
|d        y)u   task md (cron prompt)에 finalize chain 명시가 빠져 있으면 wrapper가 footer를 자동 삽입.

    safe_cron_dispatch가 ALLOWED 상태로 진입하고 audit/preview에 footer가 포함된다.
    uM   [task-9001] dev2 indra: utils/feature_x.py에 새 helper 추가 + 회귀 3건2mNpromptschedulechattarget_bot_key	task_kind
session_idr=   uC   footer 자동 삽입은 preflight 통과해야 함. blocked_reason=--cron   u3   wrapper가 footer를 prompt 끝에 삽입해야 함)commitpushPRmergesmoke	reconcileu
   footer에 u    누락)r   r	   r
   
CHAIR_CHATDEV2_INDRA_KEYr   statusr   ALLOWEDblocked_reasonlistcommand_argvindex)r=   bare_promptresultargvcron_idxinjected_promptkeywords          r8   Atest_regression_2_task_md_missing_12_steps_wrapper_injects_footerrn      s    
 bK 'k999";///%F ==N222 
MfNcNcMde2
 ##$Dtzz(#H8a<(O&/9 =9 K K/)JZ{'+JJ)Kr:   opt_out_phrase)zread_only: truezread_only:truezREAD_ONLY: TRUEc           	        d|  d}t        |      s
J d|        t        t        |      rJ t        t        |      }||k(  sJ d       t        |vsJ t        |dt        t        t        d|      }|j                  t        j                  k(  sJ t        |j                        j                  d      }t        |j                  |d	z      vsJ y)
uX   read_only opt-out이 명시된 task는 자동 finalize footer가 삽입되지 않는다.u   [task-9002] audit only — u   

status scan 후 보고.   opt-out 토큰 인식 실패: u8   read_only task에 footer가 삽입됨 — opt-out 위반rP   NrQ   rX   rY   )r	   r   r   r   r   r
   r`   ra   rb   r   rc   re   rf   rg   ro   r=   rR   outri   rk   s         r8   /test_regression_3_read_only_task_skips_finalizert     s     +>*::UVFv&[*HHZ([[&1-HHH &mV
<C&=TTT=&c111  %F ==N22222F''(..x8H&f.A.A(Q,.OOOOr:   )zreport_only: truezanalysis_only: truezfinalize_policy: no_przfinalize_policy:no_prc           	     r   d|  d}t        |      s
J d|        t        t        |      }||k(  sJ t        |vsJ t	        |dt
        t        t        d|      }|j                  t        j                  k(  sJ t        |j                        j                  d      }t        |j                  |dz      vsJ y)	uS   report_only / analysis_only / finalize_policy:no_pr 모두 finalize 생략 default.u#   [task-9003] retrospective task — u   

회고만 작성.rq   rP   NrQ   rX   rY   )r	   r   r   r   r
   r`   ra   rb   r   rc   re   rf   rg   rr   s         r8   =test_regression_4_report_only_and_analysis_only_skip_finalizerv   C  s     3>2BBWXFv&[*HHZ([[&
%&;V
DC&==&c111%'F ==N22222F''(..x8H&f.A.A(Q,.OOOOr:   c                   d}t         t        t        fD ]\  }t        ||      }||k7  s
J | d       t        |v sJ t        ||      }||k(  s
J | d       |j                  t              dk(  r\J  t        t        fD ]  }t        ||      }||k(  rJ | d        t        |dt        t        t        d|       }|j                  t        j                  k(  sJ t        |j                        j!                  d	      }|j                  |dz      }t        |v sJ t#        d
ddddddddddddd      }t%        |      \  }	}
|	t&        j(                  k(  sJ |
g k(  s,J d|
D cg c]  }|j*                  j,                   c}        yc c}w )u[   code task (independent / merge / bot) 모두 footer 자동 삽입 + finalize 박제 정합.u1   [task-9004] dev2: utils/foo.py 변경 + 회귀 +1u   에서 footer 미삽입u    footer 멱등성 위반rY   u)   는 footer 자동 삽입 대상이 아님rP   NrQ   rX   z	task-9004c   MERGED
abc1234567TSUCCESSPASS	completedz2026-05-10T12:00:00Z)r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r/   u   FINALIZED 상태에서 stuck 분류는 0건이어야 함 — AUTO_FINALIZE_CHAIN_MISSING 4종이 false positive로 잡히면 안 됨. got: )r   r   r   r   r   countr   r   r
   r`   ra   rb   r   rc   re   rf   rg   r9   r   r   	FINALIZEDr@   rB   )r=   code_promptkindrs   twiceri   rk   final_promptfinalized_evidencerI   stuckss               r8   6test_regression_5_code_task_auto_enters_finalize_chainr   j  s   EK 'G =)$<k!CdV+B#CC!*c111+D#6|>v%=>>|{{671<<<= '(@A V)$<k!UdV+T#UU!V
  %F ==N22222F''(..x8H&&x!|4L&,666 (! - $  ##56LE5N,,,,,B; 	)./A/0	2; 0s   #F
c                     h d} t         D ch c]$  }|j                  d      d   j                         & }}| |z
  }|r
J d|        yc c}w )u`   회장 §명시 4 opt-out 토큰이 모두 카탈로그에 박제되어 있는지 정적 검증.>   	read_onlyreport_onlyanalysis_onlyfinalize_policy:r   u$   opt-out 토큰 카탈로그 누락: N)r   splitstrip)expected_logicaltokfoundmissings       r8   (test_opt_out_tokens_catalog_completenessr     sX    W2NO3SYYs^A$$&OEO&GH>wiHH;w Ps   )A
c                 d   t        di ddddddddd	d
dddddd
dd
dd
dddd
dddd
dd
dd} t        |       }t        j                  t        j                  t        j
                  t        j                  h}|D ch c]  }|j                   c}|z  }|r
J d|        yc c}w )ui   이미 PR이 MERGED인 task evidence는 AUTO_FINALIZE_CHAIN_MISSING 4종 어느 것도 잡히면 안 됨.r   z	task-9005r   d   r   ry   r   
def4567890r   Tr   r{   r   r|   r"   r#   r$   r    r}   r/   r2   g    ~.Ar.   r,   r-   uP   PR_MERGED 상태에서 AUTO_FINALIZE_CHAIN_MISSING이 false positive로 잡힘: Nr3   )r9   r   r   rC   COMMIT_DONE_BUT_NO_PRPR_OPEN_BUT_NO_MERGE_ATTEMPTrA   r@   )merged_evidencerF   auto_finalize_reasonsrG   	triggereds        r8   9test_auto_finalize_does_not_inject_for_merged_pr_evidencer     s   $   "	
       ! !% %-   !%  $,!O$ /E++))0033	 $))a),AAI 
Z[dZef=y *s   B-c                     t        ddddddddd	      } t        |       }|D ch c]  }|j                   }}t        j                  |v s
J d	|        yc c}w )
uQ   PR_OPEN_BUT_NO_MERGE_ATTEMPT — pr_state=OPEN + ci=SUCCESS + 5분+ 경과한 PR.z	task-9006   OPENNr{   r?   T)	r   r   r   r   r   r1   r+   r,   r.   u@   PR_OPEN + CI SUCCESS + 10분 경과인데 stuck 분류 안 됨: )r9   r   r@   r   r   stuck_evidencerF   rG   rH   s       r8   +test_pr_open_but_no_merge_attempt_detectionr     st    #! $
N ~.E!&'Aqxx'G'33w> 
J7)T> (s   Ac            
         t        dddddddd      } t        |       }|D ch c]  }|j                   }}t        j                  |v s
J d|        yc c}w )uI   COMMIT_DONE_BUT_NO_PR — branch push되었지만 PR 없고 5분+ 경과.z	task-9007NTr?   )r   r   r   r   r+   r,   r.   r-   uD   branch_push + PR missing + 10분 경과인데 stuck 분류 안 됨: )r9   r   r@   r   r   r   s       r8   $test_commit_done_but_no_pr_detectionr     sq    # $#(	N ~.E!&'Aqxx'G',,7 
NwiX7 (s   A)returnr   )r<   r   r   r   )r=   r   )ro   strr=   r   )4__doc__
__future__r   syspathlibr   pytest__file__resolveparent_WORKTREE_ROOTr   pathremoveinsertscripts.safe_cron_dispatchr   r   r   r   r	   r
   r   utils.cron_targeting_auditr   r   r   r   r   &utils.lifecycle_reconciliation_managerr   r   r   r   r   r`   ra   r9   fixturer=   rK   rN   rn   markparametrizert   rv   r   r   r   r   r   r3   r:   r8   <module>r      sd   B # 
  
 h'')0077>>~#(("HHOOC'( 3~& '     
#%D 3 3"9V?9L%KX PP> PP%)PP<:BIB(r:   