
    j*2                    v   d Z ddlmZ ddlZddlmc mZ ddl	Z	e	j                  j                  dd       ddlZddlZddlZej                  j!                  dd       ddlmZmZmZmZmZmZmZ ddZ G d	 d
      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z y)u  Tests for v3.6 Layer 3: Watchdog Suppression Gate.

chair_authorization_id=CHAIR-AUTH-TASK-2704-V36-CONTROL-PLANE-P0-MVP-260528

Coverage:
- Alive OR-7 each branch (chat_allowed=False when alive signal present)
- ALERT_INFO/ALERT_WARN: chat_allowed=False
- ESCALATE_CHAIR: chat_allowed=True (only case)
- .escalate marker → immediate SUPPRESSED (task-2405 fix#A)
- hb_age=-1 AND ev_age=-1 alone must NOT escalate
    )annotationsNz/home/jay/workspaceANU_V36_HARNESS_TEST_MODE1)evaluate_alertQUIETWATCH
ALERT_INFO
ALERT_WARNESCALATE_CHAIR
SUPPRESSEDc                     t        d| ||d|S )Ntask_idhb_ageev_age )r   )r   r   r   kwargss       K/home/jay/workspace/tests/harness/test_v36_watchdog_suppression_contract.pycallr   %   s    R'&R6RR    c                      e Zd ZdZd Zd Zy)TestHbEvNegativeOneAloneuR   hb_age=-1 AND ev_age=-1 alone MUST NOT trigger escalation (per spec §contract#3).c                   t        ddddddddd	      }|d   }|t        k7  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }t        j                  d	      d
z   d|iz  }t        t        j                  |            d x}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )NF)	r   r   _override_dispatch_marker_override_closeout_marker_override_escalate_marker_override_spawn_ge_work_started_override_bot_session_active_override_worktree_mtime_lt_900_override_artifact_mtime_lt_900verdict)!=)z%(py1)s != %(py3)sr   py1py3zAhb_age=-1 and ev_age=-1 alone must NOT escalate to ESCALATE_CHAIRz
>assert %(py5)spy5chat_allowedisz%(py1)s is %(py4)sr%   py4assert %(py6)spy6)r   r   
@pytest_ar_call_reprcompare	_saferepr@py_builtinslocals_should_repr_global_name_format_assertmsgAssertionError_format_explanation	selfresult@py_assert0@py_assert2@py_format4@py_format6@py_assert3@py_format5@py_format7s	            r   ;test_hb_ev_both_neg1_no_alive_signals_is_watch_not_escalatezTTestHbEvNegativeOneAlone.test_hb_ev_both_neg1_no_alive_signals_is_watch_not_escalate.   s   b&+&+&+,1).,1,1	
 i  	
 N2 	
 	
 N 	
 	
 		 ! 	
 	
	6	
 	
  %3 	
 	
 		 %3 	
 	
  P	
 	
 	
 	
 	
 n%..%....%...%..........r   c                B   t        dd      }|d   }t        t        t        t        f}||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
}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nr   )r   r   r"   inz%(py1)s in %(py4)sr,   r.   r/   r(   Fr)   r+   )
r   r   r   r   r	   r0   r1   r2   r7   r8   r:   r;   r<   r@   r=   rA   rB   s          r   "test_hb_ev_both_neg1_returns_watchz;TestHbEvNegativeOneAlone.test_hb_ev_both_neg1_returns_watch>   s    R+i JUE:z$JJ $JJJJJ $JJJJ JJJ$JJJJJJJJn%..%....%...%..........r   N)__name__
__module____qualname____doc__rC   rI   r   r   r   r   r   +   s    \/ /r   r   c                  :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
TestAliveOR7z:Each of the 7 alive signals independently suppresses chat.c                *   t        dddddddddd
      }|d   }d}||u }|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 )N'     TF
r   r   consecutive_stalled_cyclesr   r   r   r   r   r    r!   r(   r)   r+   r,   r.   r/   dispatch_markeralive_signalsrE   rG   r   r0   r1   r2   r7   r8   rH   s          r   -test_signal_1_dispatch_marker_suppresses_chatz:TestAliveOR7.test_signal_1_dispatch_marker_suppresses_chatH   s    '(&*&+&+,1).,1,1

 n%..%....%...%.......... ;F?$;; $;;;;; $;;;; ;;;$;;;;;;;;r   c                *   t        dddddddddd
      }|d   }d}||u }|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 )NrQ   rR   FTrS   r(   r)   r+   r,   r.   r/   closeout_markerrV   rE   rG   rW   rH   s          r   -test_signal_2_closeout_marker_suppresses_chatz:TestAliveOR7.test_signal_2_closeout_marker_suppresses_chatW   s    '(&+&*&+,1).,1,1

 n%..%....%...%.......... ;F?$;; $;;;;; $;;;; ;;;$;;;;;;;;r   c                   t        ddd      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              nddz  }d	d
|iz  }t        t        j                  |            dx}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)uF   Escalate marker → SUPPRESSED (not just chat=False, full SUPPRESSED).rQ   T)r   r   r   r"   ==z%(py1)s == %(py3)sr   r$   assert %(py5)sr'   Nr(   Fr)   r+   r,   r.   r/   )
r   r   r0   r1   r2   r3   r4   r5   r7   r8   r9   s	            r   1test_signal_3_escalate_marker_triggers_suppressedz>TestAliveOR7.test_signal_3_escalate_marker_triggers_suppressedf   s    &*
 i . J.... J... ......J...J.......n%..%....%...%..........r   c                *   t        dddddddddd
      }|d   }d}||u }|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 )NrQ   rR   FTrS   r(   r)   r+   r,   r.   r/   spawn_ge_work_startedrV   rE   rG   rW   rH   s          r   3test_signal_4_spawn_ge_work_started_suppresses_chatz@TestAliveOR7.test_signal_4_spawn_ge_work_started_suppresses_chato   s    '(&+&+&+,0).,1,1

 n%..%....%...%..........&A&*AA&*AAAAA&*AAAA&AAA*AAAAAAAAr   c                *   t        dddddddddd
      }|d   }d}||u }|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 )NrQ   rR   FTrS   r(   r)   r+   r,   r.   r/   bot_session_activerV   rE   rG   rW   rH   s          r   0test_signal_5_bot_session_active_suppresses_chatz=TestAliveOR7.test_signal_5_bot_session_active_suppresses_chat~   s    '(&+&+&+,1)-,1,1

 n%..%....%...%..........#>vo'>>#'>>>>>#'>>>>#>>>'>>>>>>>>r   c                *   t        dddddddddd
      }|d   }d}||u }|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 )NrQ   rR   FTrS   r(   r)   r+   r,   r.   r/   worktree_mtime_lt_900rV   rE   rG   rW   rH   s          r   ,test_signal_6_worktree_fresh_suppresses_chatz9TestAliveOR7.test_signal_6_worktree_fresh_suppresses_chat   s    '(&+&+&+,1).,0,1

 n%..%....%...%..........&A&*AA&*AAAAA&*AAAA&AAA*AAAAAAAAr   c                *   t        dddddddddd
      }|d   }d}||u }|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 )NrQ   rR   FTrS   r(   r)   r+   r,   r.   r/   artifact_mtime_lt_900rV   rE   rG   rW   rH   s          r   ,test_signal_7_artifact_fresh_suppresses_chatz9TestAliveOR7.test_signal_7_artifact_fresh_suppresses_chat   s    '(&+&+&+,1).,1,0

 n%..%....%...%..........&A&*AA&*AAAAA&*AAAA&AAA*AAAAAAAAr   N)rJ   rK   rL   rM   rX   r[   ra   rd   rg   rj   rm   r   r   r   rO   rO   E   s+    D<</B?BBr   rO   c                      e Zd ZdZd Zd Zy)TestAlertInfoWarnNoChatAllowedz0ALERT_INFO and ALERT_WARN must never allow chat.c                   t        dddddddddd
      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndd	z  }d
d|iz  }t        t        j                  |            d x}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )N     FrS   r"   r]   r_   r	   r$   r`   r'   r(   r)   r+   r,   r.   r/   )
r   r	   r0   r1   r2   r3   r4   r5   r7   r8   r9   s	            r    test_alert_info_chat_not_allowedz?TestAlertInfoWarnNoChatAllowed.test_alert_info_chat_not_allowed   s    '(&+&+&+,1).,1,1

 i . J.... J... ......J...J.......n%..%....%...%..........r   c                   t        ddddddddddd      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndd	z  }d
d|iz  }t        t        j                  |            d x}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nrq      Fr   r   rT   is_critical_7r   r   r   r   r   r    r!   r"   r]   r_   r
   r$   r`   r'   r(   r)   r+   r,   r.   r/   )
r   r
   r0   r1   r2   r3   r4   r5   r7   r8   r9   s	            r    test_alert_warn_chat_not_allowedz?TestAlertInfoWarnNoChatAllowed.test_alert_warn_chat_not_allowed   s    '(&+&+&+,1).,1,1
 i . J.... J... ......J...J.......n%..%....%...%..........r   N)rJ   rK   rL   rM   rs   rx   r   r   r   ro   ro      s    ://r   ro   c                      e Zd ZdZd Zd Zy)TestEscalateChairOnlyAllowsChatz+chat_allowed=True ONLY when ESCALATE_CHAIR.c                   t        ddddddddddd      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      d	t        j                         v st        j                  t              rt        j                  t              nd	d
z  }dd|iz  }t        t        j                  |            d x}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nrq   ru   TFrv   r"   r]   r_   r   r$   r`   r'   r(   r)   r+   r,   r.   r/   
r   r   r0   r1   r2   r3   r4   r5   r7   r8   r9   s	            r   test_escalate_chair_allows_chatz?TestEscalateChairOnlyAllowsChat.test_escalate_chair_allows_chat   s    '(&+&+&+,1).,1,1
 i 2 N2222 N222 222222N222N2222222n%--%----%---%----------r   c                   t        ddddddddddd      }|d   }|t        k(  }|st        j                  d|fd|t        f      t        j                  |      d	t        j                         v st        j                  t              rt        j                  t              nd	d
z  }dd|iz  }t        t        j                  |            d x}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nrq   ru   TF)r   r   rT   explicit_chair_escalater   r   r   r   r   r    r!   r"   r]   r_   r   r$   r`   r'   r(   r)   r+   r,   r.   r/   r|   r9   s	            r   %test_escalate_chair_via_explicit_flagzETestEscalateChairOnlyAllowsChat.test_escalate_chair_via_explicit_flag   s    '($(&+&+&+,1).,1,1
 i 2 N2222 N222 222222N222N2222222n%--%----%---%----------r   N)rJ   rK   rL   rM   r}   r   r   r   r   rz   rz      s    5. .r   rz   c                      e Zd ZdZd Zd Zy)TestEscalateMarkerTask2405u;   task-2405 fix#A: .escalate marker → immediate SUPPRESSED.c                N   t        |      }t        j                  j                  |d      }t	        |d      5 }|j                  d       d d d        t        ddd|      }|d   }|t        k(  }|st        j                  d|fd	|t        f      t        j                  |      d
t        j                         v st        j                  t              rt        j                  t              nd
dz  }dd|iz  }	t        t        j                  |	            d x}}|d   }d}
||
u }|slt        j                  d|fd||
f      t        j                  |      t        j                  |
      dz  }dd|iz  }t        t        j                  |            d x}x}}
y # 1 sw Y   RxY w)Nztask-2704.escalatew 	task-2704rQ   r   r   r   
events_dirr"   r]   r_   r   r$   r`   r'   r(   Fr)   r+   r,   r.   r/   strospathjoinopenwriter   r   r0   r1   r2   r3   r4   r5   r7   r8   r:   tmp_pathr   escalate_pathfhr;   r<   r=   r>   r?   r@   rA   rB   s                r   1test_escalate_marker_present_immediate_suppressedzLTestEscalateMarkerTask2405.test_escalate_marker_present_immediate_suppressed   s   ]
Z1EF-% 	HHRL	!	
 i . J.... J... ......J...J.......n%..%....%...%..........	 	   FF$c                N   t        |      }t        j                  j                  |d      }t	        |d      5 }|j                  d       d d d        t        ddd|      }|d   }|t        k(  }|st        j                  d|fd	|t        f      t        j                  |      d
t        j                         v st        j                  t              rt        j                  t              nd
dz  }dd|iz  }	t        t        j                  |	            d x}}|d   }d}
||
u }|slt        j                  d|fd||
f      t        j                  |      t        j                  |
      dz  }dd|iz  }t        t        j                  |            d x}x}}
y # 1 sw Y   RxY w)Nztask-2704.escalate.ackedr   r   r   rQ   r   r"   r]   r_   r   r$   r`   r'   r(   Fr)   r+   r,   r.   r/   r   r   s                r   /test_escalate_acked_marker_immediate_suppressedzJTestEscalateMarkerTask2405.test_escalate_acked_marker_immediate_suppressed  s   ]
Z1KL-% 	HHRL	!	
 i . J.... J... ......J...J.......n%..%....%...%..........	 	r   N)rJ   rK   rL   rM   r   r   r   r   r   r   r      s    E//r   r   c                      e Zd ZdZd Zy)TestFixtureCoveragez.All scenarios from the JSON fixture file pass.c                j   t         j                  j                  t         j                  j                  t              d      }t        |      5 }t        j                  |      }d d d        j                         D ](  \  }}|j                  di       }t        |d   |d   |d   |j                  dd      |j                  dd	      |j                  d
d	      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d            }|d   }|d   }	||	k(  }
|
st        j                  d|
fd||	f      t        j                  |      t        j                  |	      dz  }t        j                  d| d|d    d|d    d|d          dz   d|iz  }t        t        j                   |            d x}x}
}	|d   }|d    }	||	k(  }
|
st        j                  d|
fd||	f      t        j                  |      t        j                  |	      dz  }t        j                  d| d!|d     d|d          dz   d|iz  }t        t        j                   |            d x}x}
}	+ y # 1 sw Y   GxY w)"Nz$fixtures/v36_watchdog_scenarios.jsonalive_overridesr   r   r   rT   r   rw   Fr   rU   rZ   escalate_markerrc   rf   ri   rl   )r   r   r   rT   rw   r   r   r   r   r   r   r    r!   r"   expected_verdictr]   )z%(py1)s == %(py4)sr,   z
Scenario 'z': expected z, got u    — reasonz
>assert %(py6)sr/   r(   expected_chat_allowedz': expected chat_allowed=)r   r   r   dirname__file__r   jsonloaditemsgetr   r0   r1   r2   r6   r7   r8   )r:   fixture_pathr   	scenariosscenario_namescenario	overridesr;   r<   r@   r=   rA   rB   s                r   test_fixture_scenariosz*TestFixtureCoverage.test_fixture_scenarios  s   ww||GGOOH%2
 , 	&2		"I	& (1'8 	#M8 %6;I# +))+3<<8TVW+X&ll?EB(05NPU(V*3--8I*J*3--8I*J*3--8I*J09>U0V-6]];O-P09>U0V09>U0VF )$ 1C(D $(DD  $(D   I %   I )E    ]O<AS8T7U Vi()vh/?.@B     .) X6M-N )-NN  )-N   I *   I .O    ]O+DXNeEfDg hn-.0     +		& 	&s   J((J2N)rJ   rK   rL   rM   r   r   r   r   r   r     s
    8 r   r   c                      e Zd Zd Zy)TestSafeFailc                   	 t        dd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}}y# t        $ r t        j                  d
       Y yw xY w)z!evaluate_alert must be safe-fail.N
not_an_intr   )is not)z%(py0)s is not %(py3)sr;   )py0r&   r`   r'   z6evaluate_alert must not raise on bad input (safe-fail))r   r0   r1   r3   r4   r5   r2   r7   r8   	Exceptionpytestfail)r:   r;   r=   @py_assert1r>   r?   s         r   -test_evaluate_alert_never_raises_on_bad_inputz:TestSafeFail.test_evaluate_alert_never_raises_on_bad_input:  s    	R##F
 "&%6%%%%6%%%%%%6%%%6%%%%%%%%%% 	RKKPQ	Rs   B3B6 6CCN)rJ   rK   rL   r   r   r   r   r   r   9  s    
Rr   r   )r   r   r   )!rM   
__future__r   builtinsr3   _pytest.assertion.rewrite	assertionrewriter0   sysr   insertr   r   r   environ
setdefault-scripts.harness.v36.watchdog_suppression_gater   r   r   r	   r
   r   r   r   r   rO   ro   rz   r   r   r   r   r   r   <module>r      s   
 #   
 ( )  	  

  13 7  S/ /4dB dBN /  /F!. !.H/ /@# #LR Rr   