
    jH5              	          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	ej                  j                  dej                  j                  ej                  j                  e      ddd             ddlZej                  j                  ej                  j                  e      dd      Z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 d Z!d Z"d Z#d Z$d Z%d Z&y)u   
test_codex_review_loop_decider_2711.py
task-2711 QA — ANU_CODEX_REVIEW_LOOP_DECIDER 테스트
작성자: 아르고스 (dev1팀 QA 엔지니어)

14개 시나리오 + 2개 메타 테스트 = 총 16개 함수
    Nz..scriptsanufixturescodex_review_2711filenamereturnc                    t         j                  j                  t        |       }t	        |dd      5 }t        j                  |      }ddd       t        j                        }t        j                  |      S # 1 sw Y   3xY w)u8   JSON fixture 파일을 읽어 decide() 결과를 반환.rzutf-8)encodingN)
ospathjoinFIXDIRopenjsonloadcrld	from_dictdecide)r   r   fdatainps        @/home/jay/workspace/tests/test_codex_review_loop_decider_2711.py_load_fixturer      sc    77<<)D	dC'	* ayy|
..
C;;s s   A;;Bc                     t        d      } | 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z   d	|iz  }t        t        j                  |            d
x}x}}y
)u-   Round 1: 전체 NR → AUTO_REVISION_CONTINUEtask-2710_round1.jsonAUTO_REVISION_CONTINUE==z0%(py2)s
{%(py2)s = %(py0)s.decision
} == %(py5)sresultpy0py2py5%Expected AUTO_REVISION_CONTINUE, got 
>assert %(py7)spy7Nr   decision
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgAssertionError_format_explanationr!   @py_assert1@py_assert4@py_assert3@py_format6@py_format8s         r   test_t1_round1_needs_revisionr:   "       23F?? 6 ?66  ?6                  7    0/@A         c                     t        d      } | 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z   d	|iz  }t        t        j                  |            d
x}x}}y
)u`   Round 6: PASS_WITH_RECOMMENDATIONS + pilot NOT_READY_WITHOUT_FOLLOWUP → AUTO_REVISION_CONTINUEztask-2710_round6.jsonr   r   r    r!   r"   r&   r'   r(   Nr)   r4   s         r   "test_t2_round6_pwr_pilot_not_readyr>   *   r;   r<   c                     t        d      } | 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z   d	|iz  }t        t        j                  |            d
x}x}}y
)u\   Round 7: pilot READY_WITH_RECOMMENDATIONS, chair_minor=False → PILOT_READY_BUT_NEEDS_CHAIRz'task-2710_round7_chair_minor_false.jsonPILOT_READY_BUT_NEEDS_CHAIRr   r    r!   r"   *Expected PILOT_READY_BUT_NEEDS_CHAIR, got r'   r(   Nr)   r4   s         r   !test_t3a_round7_chair_minor_falserB   2   s    DEF?? ; ?;;  ?;                  <    5V__4EF     r<   c                     t        d      } | 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z   d	|iz  }t        t        j                  |            d
x}x}}y
)uV   Round 7: pilot READY_WITH_RECOMMENDATIONS, chair_minor=True → AUTO_REVISION_CONTINUEz&task-2710_round7_chair_minor_true.jsonr   r   r    r!   r"   r&   r'   r(   Nr)   r4   s         r    test_t3b_round7_chair_minor_truerD   :   s    CDF?? 6 ?66  ?6                  7    0/@A     r<   c                     t        d      } | 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z   d	|iz  }t        t        j                  |            d
x}x}}y
)uH   v8: PASS_WITH_RECOMMENDATIONS, remaining=[], locked=False → LOCK_READYztask-2710_v8_lock_ready.json
LOCK_READYr   r    r!   r"   zExpected LOCK_READY, got r'   r(   Nr)   r4   s         r   test_t4_v8_lock_readyrG   B   s    9:F?? l ?l*  ?l                  +    $FOO#45     r<   c                     t        d      } | 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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}}y
)uX   evidence reclassify: trigger6 발동 → CRITICAL_ESCALATION, 6 in risk_triggers_matchedz,critical_escalation_evidence_reclassify.jsonCRITICAL_ESCALATIONr   r    r!   r"   "Expected CRITICAL_ESCALATION, got r'   r(   N   inz=%(py1)s in %(py5)s
{%(py5)s = %(py3)s.risk_triggers_matched
}py1py3r%   z1Expected trigger 6 in risk_triggers_matched, got )r   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   risk_triggers_matched)r!   r5   r6   r7   r8   r9   @py_assert0@py_assert2s           r   $test_t5_critical_evidence_reclassifyrU   J   s   IJF?? 3 ?33  ?3                  4    -V__,=>      ,, 1,,  1,                  -    <F<X<X;YZ     r<   c                     t        d      } | 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z   d	|iz  }t        t        j                  |            d
x}x}}y
)u>   동일 blocker 3회 반복 §5.4.1 → CHAIR_DECISION_REQUIREDz!loop_boundary_same_blocker_3.jsonCHAIR_DECISION_REQUIREDr   r    r!   r"   &Expected CHAIR_DECISION_REQUIRED, got r'   r(   Nr)   r4   s         r   test_t7a_same_blocker_3_roundsrY   U   s    >?F?? 7 ?77  ?7                  8    10AB     r<   c                     t        d      } | 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z   d	|iz  }t        t        j                  |            d
x}x}}y
)u9   FAIL 2회 같은 axis §5.4.2 → CHAIR_DECISION_REQUIREDz#loop_boundary_fail_2_same_axis.jsonrW   r   r    r!   r"   rX   r'   r(   Nr)   r4   s         r   test_t7b_fail_2_same_axisr[   ]   s    @AF?? 7 ?77  ?7                  8    10AB     r<   c                  N   dddddddddd	g d
ddd
} t        j                  t        j                  |             }|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z   d|iz  }t        t	        j                  |            dx}x}}y)um   locked_status=True, pilot READY, remaining=[] → LOCK_READY 조건 미충족 → PILOT_READY_BUT_NEEDS_CHAIRz	task-2710      PASS_WITH_RECOMMENDATIONSREADY      r   passpwrnrfailTzCHAIR-AUTH-T6-PLACEHOLDERF)
task_idversionround_numberoverall_verdictpilot_readinessaxis_countsremaining_recommendationslocked_statuschair_authorization_id"chair_minor_doc_cleanup_authorizedr@   r   r    r!   r"   rA   r'   r(   Nr   r   r   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   dr!   r5   r6   r7   r8   r9   s          r   test_t6_lock_ready_then_pilotru   i   s    6" !!1a@%'"=.3	A [[*+F?? ; ?;;  ?;                  <    5V__4EF     r<   c            
      "   ddddddddddd	gd
dd	} t        j                  t        j                  |             }|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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}}y)uh   remaining에 'Critical 7 doctrine 위반 — CHAIR_REQUIRED' → trigger1 발동 → CRITICAL_ESCALATION	task-2799   rb   NEEDS_REVISIONNOT_READY_WITHOUT_FOLLOWUPr   ra   rc   u-   Critical 7 doctrine 위반 — CHAIR_REQUIREDFzCHAIR-AUTH-T8-PLACEHOLDER	rh   ri   rj   rk   rl   rm   rn   ro   rp   rI   r   r    r!   r"   rJ   r'   r(   NrL   rN   rO   z1Expected trigger 1 in risk_triggers_matched, got r   r   r   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   rR   	rt   r!   r5   r6   r7   r8   r9   rS   rT   s	            r   test_t8_critical7_keywordr~   }   s    +7 !!1a@;&
 "=	A [[*+F?? 3 ?33  ?3                  4    -V__,=>      ,, 1,,  1,                  -    <F<X<X;YZ     r<   c            
      "   dddddddddddgd	d
d	} t        j                  t        j                  |             }|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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}}y)uW   remaining에 §11.3 forbidden target → trigger3만 발동 → CHAIR_DECISION_REQUIREDrw   rx   rb   ry   rz   r   rc   u2   §11.3 forbidden target 에 새 path 추가 필요FzCHAIR-AUTH-T9-PLACEHOLDERr{   rW   r   r    r!   r"   rX   r'   r(   Nra   rL   rN   rO   z1Expected trigger 3 in risk_triggers_matched, got r|   r}   s	            r   test_t9_forbidden_path_changer      s    +7 !!1a@@&
 "=	A [[*+F?? 7 ?77  ?7                  8    10AB      ,, 1,,  1,                  -    <F<X<X;YZ     r<   c            
      $   dddddddddddd	gd
dd	} t        j                  t        j                  |             }|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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}}y)uX   remaining에 dispatch.py + bot_settings.json → trigger4 발동 → CRITICAL_ESCALATIONrw   rx   rb   ry   rz   r   rc   u   dispatch.py 변경 필요u   bot_settings.json 변경FzCHAIR-AUTH-T10-PLACEHOLDERr{   rI   r   r    r!   r"   rJ   r'   r(   N   rL   rN   rO   1Expected trigger 4 in risk_triggers_matched, got r|   r}   s	            r    test_t10_actual_dispatch_requestr      s    +7 !!1a@'&&
 ">	A [[*+F?? 3 ?33  ?3                  4    -V__,=>      ,, 1,,  1,                  -    <F<X<X;YZ     r<   c            
      "   dddddddddddgd	d
d	} t        j                  t        j                  |             }|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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}}y)uk   remaining에 'new allowed_path 추가 권한 확대 요청' → trigger2 발동 → CHAIR_DECISION_REQUIREDrw   rx   rb   ry   rz   r   rc   u,   new allowed_path 추가 권한 확대 요청FzCHAIR-AUTH-T11-PLACEHOLDERr{   rW   r   r    r!   r"   rX   r'   r(   NrL   rN   rO   z1Expected trigger 2 in risk_triggers_matched, got r|   r}   s	            r   test_t11_permission_expansionr      s    +7 !!1a@:&
 ">	A [[*+F?? 7 ?77  ?7                  8    10AB      ,, 1,,  1,                  -    <F<X<X;YZ     r<   c            
      "   dddddddddddgd	d
d	} t        j                  t        j                  |             }|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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}}y)uW   remaining에 'PR 생성 + git push + merge' → trigger4 발동 → CRITICAL_ESCALATIONrw   rx   rb   ry   rz   r   rc   u9   revision 산출물에 PR 생성 + git push + merge 포함FzCHAIR-AUTH-T12-PLACEHOLDERr{   rI   r   r    r!   r"   rJ   r'   r(   Nr   rL   rN   rO   r   r|   r}   s	            r   (test_t12_revision_includes_pr_push_merger      s    +7 !!1a@G&
 ">	A [[*+F?? 3 ?33  ?3                  4    -V__,=>      ,, 1,,  1,                  -    <F<X<X;YZ     r<   c            
      "   dddddddddddgd	d
d	} t        j                  t        j                  |             }|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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}}y)u`   remaining에 'finish-task.sh immutable scope 수정' → trigger5 발동 → CRITICAL_ESCALATIONrw   rx   rb   ry   rz   r   rc   uP   allowed_existing_file_edits 가 finish-task.sh 를 immutable scope 에서 수정FzCHAIR-AUTH-T13-PLACEHOLDERr{   rI   r   r    r!   r"   rJ   r'   r(   N   rL   rN   rO   z1Expected trigger 5 in risk_triggers_matched, got r|   r}   s	            r   test_t13_immutable_scope_editr      s    +7 !!1a@^&
 ">	A [[*+F?? 3 ?33  ?3                  4    -V__,=>      ,, 1,,  1,                  -    <F<X<X;YZ     r<   c                  P   ddddddddddd	gd
ddd
} t        j                  t        j                  |             }|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z   d|iz  }t        t	        j                  |            dx}x}}y)uK   round_number=8 > 7 boundary → risk trigger 없이 CHAIR_DECISION_REQUIREDrw   rx   r]   ry   	NOT_READYr   rb   rc   u   minor doc 정리FzCHAIR-AUTH-T14-PLACEHOLDERN)
rh   ri   rj   rk   rl   rm   rn   ro   rp   prior_rounds_historyrW   r   r    r!   r"   z2Expected CHAIR_DECISION_REQUIRED (max round), got r'   r(   rr   rs   s          r   test_t14_max_7_roundr     s    +& !!1a@&
 "> $	A [[*+F?? 7 ?77  ?7                  8    =V__<MN     r<   c                     t         j                  t           } g d}|D ]0  }t        | |      }|st	        j
                  d|       dz   dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |       rt	        j                  |       nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dz  }t        t	        j                  |            d}3 y)	uW   14개 시나리오 함수 이름이 모두 이 모듈에 존재하는지 sanity 확인.)r:   r>   rB   rD   rG   rU   ru   rY   r[   r~   r   r   r   r   r   r   zMissing test function: z7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}hasattrthis_modulename)r#   rP   r$   py4N)sysmodules__name__r   r+   r1   r-   r.   r/   r0   r2   r3   )r   expected_testsr   r7   @py_format5s        r   "test_total_14_scenarios_documentedr   (  s    ++h'KN*  L{D)K)KK-DTF+KKKKKKKwKKKwKKKKKK{KKK{KKKKKKDKKKDKKK)KKKKKKLr<   c                  P   h d} t        d      }d}t        ||      }|st        j                  d      dz   dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d	x}}d
}t        ||      }|st        j                  d      dz   dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d	x}}d}t        ||      }|st        j                  d      dz   dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d	x}}d}t        ||      }|st        j                  d      dz   dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d	x}}d}t        ||      }|st        j                  d      dz   dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d	x}}d}t        ||      }|st        j                  d      dz   dt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            d	x}}|j                  }|| v }|s t        j                  d|fd|| f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dt	        j
                         v st        j                  |       rt        j                  |       nddz  }t        j                  d|j                   d|        dz   d|iz  }t        t        j                  |            d	x}}y	)uV   DecisionResult 6개 필드 모두 존재 + decision이 5 enum 중 하나임을 검증.>   rF   rI   r   rW   r@   r   r*   zMissing field: decisionz7
>assert %(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
}r   r!   )r#   rP   rQ   r%   N	rationalezMissing field: rationalenext_actionzMissing field: next_actionrR   z$Missing field: risk_triggers_matchedchair_facing_summaryz#Missing field: chair_facing_summaryaudit_marker_pathz Missing field: audit_marker_pathrL   )z0%(py2)s
{%(py2)s = %(py0)s.decision
} in %(py4)sVALID_DECISIONS)r#   r$   r   z
decision 'z' is not in valid set z
>assert %(py6)spy6)r   r   r+   r1   r-   r.   r/   r0   r2   r3   r*   r,   )	r   r!   rT   r6   r8   r5   r7   r   @py_format7s	            r   "test_decision_result_schema_fieldsr   E  s'   O 23F &A76:&A&AA(AAAAAAA7AAA7AAAAAA6AAA6AAA:AAA&AAAAAA&C76;'C'CC)CCCCCCC7CCC7CCCCCC6CCC6CCC;CCC'CCCCCC(G76=)G)GG+GGGGGGG7GGG7GGGGGG6GGG6GGG=GGG)GGGGGG2[7623[3[[5[[[[[[[7[[[7[[[[[[6[[[6[[[2[[[3[[[[[[1Y7612Y2YY4YYYYYYY7YYY7YYYYYY6YYY6YYY1YYY2YYYYYY.S76./S/SS1SSSSSSS7SSS7SSSSSS6SSS6SSS.SSS/SSSSSS ?? ?o-   ?o                    .    .    V__%%;O;LM    r<   )'__doc__builtinsr-   _pytest.assertion.rewrite	assertionrewriter+   r   r   r   r   insertr   dirname__file__codex_review_loop_deciderr   r   strDecisionResultr   r:   r>   rB   rD   rG   rU   rY   r[   ru   r~   r   r   r   r   r   r   r   r    r<   r   <module>r      s     
 	  277<< 94ER S (
 
bggooh/=P	QC D$7$7 (0020004L:r<   