
    j]                    F   U d Z ddlmZ ddlmZ ddddddZd	e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dddddddddddddZded<   d dZd!dZ	d!dZ
d!dZd!dZd!dZd!dZd!dZd!dZe	e
eeeeeedZd"dZd#dZy)$u  v3.6 Runtime Harness — finish-task profile judge (P1-B §10, 192-cell matrix).

chair_authorization_id=CHAIR-AUTH-TASK-2706-V36-FINISH-TASK-PROFILE-LAYER-P1B-260529

Implements §10 eight gate evaluation + §11 four-grade decision for
each task_mode per the 192-cell matrix (6 modes × 8 gates × 4 grades).

Public API
----------
- ``evaluate_gates(task_mode, gate_inputs)`` → dict (full profile gates section)
- ``compute_overall(gates_result)``            → tuple[str, str] (overall_result, rationale)
- ``SEVERITY``                                  — grade-to-int mapping

Gate inputs expected keys (all optional, missing = N/A):
    G1: commit_info(dict), lock_sha(str|None), diff_paths(list[str]),
        expected_paths(list[str])
    G2: smoke_result(dict|None)
    G3: scope_diff_paths(list[str]), expected_paths(list[str]),
        forbidden_paths(list[str]), lock_sha(str|None),
        main_diff_paths(list[str]|None)
    G4: dirty_count(int), dirty_classification(str)
    G5: qc_result(dict|None)
    G6: lineage_sha_changed(bool|None)
    G7: (schema only, not yet implemented — P1-C)
    G8: callback_registered(bool|None), envelope_bytes(int|None)

Safe-fail: never raises; any exception produces ESCALATE with error note.
    )annotations   )	GATE_KEYS      )PASSWARNFAILESCALATEN/Azdict[str, int]SEVERITYstrictmediumschema_only)G1_git_evidenceG2_L1_smokeG3_scope_guardG4_dirty_workspaceG5_qc_verificationG6_lineage_preservationG7_actor_attributionG8_callback_enforcementlenientna)codesystem_hooklocal_runtime	read_onlycallback_onlycloseout_marker_onlyUNKNOWNzdict[str, dict[str, str]]_WEIGHT_MATRIXc                    | ||dS )Nresultevidence	rationale r%   s      D/home/jay/workspace/scripts/harness/v36/finish_task_profile_judge.py_gate_resultr+      s    (KK    c                R   	 t         j                  | i       j                  dd      }|dk(  rt        ddd      S |j                  d      }|j                  d      }|j                  d      xs g }|j                  d	      xs g }|s!|s|d
k(  rt        ddd      S t        ddd      S g }|r |j                  dt	        |      dd         |r|j                  d|dd         |r|j                  dt        |              |rV|rT|D cg c]  t        fd|D              s }	}|	r.|d
k(  r)t        ddj                  |      dt        |	       d      S t        ddj                  |      xs dd      S c c}w # t        $ r}
t        dd|
 d       cY d}
~
S d}
~
ww xY w)!u7   G1: git_evidence — commit info + lock_sha..HEAD diff.r   r   r   not_applicablez"G1 not required for this task_modecommit_infolock_sha
diff_pathsexpected_pathsr   r   no_commit_info_no_diffz4G1 strict: no commit info and no diff paths providedr
   no_commit_infou6   G1: missing commit info — cannot verify git evidencezcommit_info=NP   	lock_sha=   zdiff_paths=c              3  ^   K   | ]$  }j                  |j                  d              & yw)*N)
startswithrstrip).0epps     r*   	<genexpr>z_evaluate_G1.<locals>.<genexpr>   s"     $[bQ\\"))C.%A$[s   *-; zG1: z" diff paths outside expected scoper	   commit_presentzG1 evidence verifiedr   zG1_exception: u#   G1 internal error — safe escalate)	r#   getr+   appendstrlenanyjoin	Exception)	task_modeinputsweightr/   r0   r1   r2   evidence_partsr>   
unexpectedexcs           `  r*   _evaluate_G1rO      s   -g##Ir2667H$OT>'79]^^jj/::j)ZZ-3
$45;:!#,J 
   H  !!L[1A#21F0G"HI!!Ihsm_"=>!!KJ/@"AB j%/ ]!$$[N$[![  ]J ]f0#IIn-3z?++MN  FDIIn$=$QAQSijj]  gJ.(>@effgsH   7F A!F F *A%F E>,1F F >F 	F&F!F&!F&c                   	 t         j                  | i       j                  dd      }|dk(  rt        ddd      S |j                  d      }||dk(  rt        d	d
d      S t        dd
d      S t        |t              rY|j                  dd      }|dk(  rt        dd| d      S |dv rt        d	d| d      S |dv rt        |dk7  rdndd| d|       S t        d	dd      S # t
        $ r}t        dd| d      cY d}~S d}~ww xY w)u9   G2: L1_smoke — server restart + API curl or Playwright.r   r   r   r.   z"G2 not required for this task_modesmoke_resultNr   r
   smoke_not_runz G2 strict: L1 smoke not executedz%G2: smoke not available for this taskstatusr"   r	   zsmoke_status=zG2 L1 smoke PASSr
   zG2 L1 smoke WARNr   ERRORr   zG2 L1 smoke smoke_result_ambiguousz$G2: smoke result could not be parsedr   zG2_exception: u#   G2 internal error — safe escalater#   rB   r+   
isinstancedictrH   )rI   rJ   rK   rQ   rS   rN   s         r*   _evaluate_G2r[      sG   g##Ir266}dKT>'79]^^zz.1!#FO=_``8_``lD)!%%h	:F#FmF8,DFXYY"#FmF8,DFXYY**#$0Ff#F8,"6(+  F$<>dee gJ.(>@effgs@   7C" $C" C" ,6C" #C" 7C" C" "	D+D :D Dc                   	 t         j                  | i       j                  dd      }|dk(  rt        ddd      S |j                  d      xs g }|j                  d      xs g }|j                  d      xs g }|j                  d	      }|j                  d
      }g }g }	|r|j                  d|dd         nl|j                  d       |Yt	        |      t	        |      dz   kD  r?|j                  dt	        |       dt	        |              |dk(  r|	j                  d       g }
|D ]Q  }|D ]J  }|j                  d      j                  d      }||k(  s|j                  |      s:|
j                  |       L S |
r1|	j                  d|
        |j                  dt	        |
              g }|rQ|rO|D ]J  }d}|D ]-  }|j                  d      }||k(  s|j                  |      s+d} n |r:|j                  |       L |rj|j                  dt	        |              t	        |      dk\  r|	j                  dt	        |       d       n |r|	j                  dt	        |       d       |	s t        dd j                  |      xs d!d"      S t        d# |	D              }t        d$ |	D              }t        d% |	D              }|s|r3|dk(  r.t        d&d j                  |      d'd j                  |	             S |r9|d(v r5t        |dk(  rd&nd)d j                  |      d*d j                  |	             S |dk(  r.t        d)d j                  |      d+d j                  |	             S t        d,d j                  |      d-d j                  |	             S # t        $ r}t        d&d.| d/      cY d}~S d}~ww xY w)0uD   G3: scope_guard — lock_sha..HEAD diff within expected_files scope.r   r   r   r.   z"G3 not required for this task_modescope_diff_pathsr2   forbidden_pathsr0   main_diff_pathsr6   Nr7   z"lock_sha=None(main..HEAD_fallback)   z
main_diff=z_vs_scope_diff=r   zmain..HEAD_misfire_detectedr9   /zforbidden_path_violation: zforbidden_hits=FTzout_of_scope=   zlarge_scope_violation:_pathszscope_violation:r	   r@   scope_cleanzG3 scope guard PASSc              3  $   K   | ]  }d |v  
 yw)forbidden_path_violationNr)   r<   vs     r*   r?   z_evaluate_G3.<locals>.<genexpr>  s     P6!;P   c              3  $   K   | ]  }d |v  
 yw)misfireNr)   rg   s     r*   r?   z_evaluate_G3.<locals>.<genexpr>  s     =Q)q.=ri   c              3  $   K   | ]  }d |v  
 yw)large_scope_violationNr)   rg   s     r*   r?   z_evaluate_G3.<locals>.<genexpr>  s     I/14Iri   r   zG3 scope_guard ESCALATE: )r   r   r   zG3 scope_guard: zG3 scope_guard FAIL: r
   zG3 scope_guard WARN: zG3_exception: u#   G3 internal error — safe escalate)
r#   rB   r+   rC   rE   r;   r:   rG   rF   rH   )rI   rJ   rK   r]   r2   r^   r0   r_   rL   
violationsforbidden_hitspathfpfp_cleanout_of_scopein_scoper=   ep_cleanhas_forbiddenhas_misfire	has_largerN   s                         r*   _evaluate_G3ry      s   _g##Ir2667GNT>'79]^^!::&89?R$45; **%67=2::j) **%67
!!Ihsm_"=>!!"FG*s?/CcJZF[^_F_/_%%
33G2HX[\lXmWn&opX%%%&CD $ 	0D% 099S>0058#tx'@"))$/0	0  :>:JKL!!OC4G3H"IJ .( . ( B!yy~Hx'4??8+D#'	
   ''-. !!M#l2C1D"EF< B&!!$:3|;L:MV"TU!!$4S5F4Gv"NO		.):]%  PZPP=*==IjII	[f.@		.)+DIIj,A+BC 
 6%99$0
f		.)"499Z#8"9: 
 x		.)'		*(='>?   		.)'		*(='>?   gJ.(>@effgsP   7N D-N (BN *N 2B N A,N  :N ;2N .-N 	N?%N:4N?:N?c           	     z   	 t         j                  | i       j                  dd      }|dk(  rt        ddd      S |j                  dd      }|j                  dd	      }d
| d| }|dk(  s|dk(  rt        d|d      S |dk(  rt        d|d      S |dk(  rt        d|d      S |dk(  rt        d|d      S |dk(  rD|dk\  rt        d|d| d      S |dk\  rt        |dk(  rdnd|d| d      S t        d|d| d      S t        |dk  rdnd|d | d!| d"      S # t        $ r}t        d#d$| d%      cY d&}~S d&}~ww xY w)'u-   G4: dirty_workspace — classify dirty state.r   r   r   r.   z"G4 not required for this task_modedirty_countr   dirty_classificationUNKNOWN_DIRTYzdirty_count=z, classification=CLEANr	   zG4 workspace clean	OWN_DIRTYz%G4 OWN_DIRTY: task's own changes onlyINHERITED_DIRTYr
   z7G4 INHERITED_DIRTY: prior task lineage residue detectedDAEMON_RECURRENCEz5G4 DAEMON_RECURRENCE: daemon-generated files detectedEXTERNAL_DIRTYi  r   zG4 EXTERNAL_DIRTY: z+ files contaminated2   r   z files contaminatedz filesd   zG4 z: z& dirty files, classification uncertainr   zG4_exception: u#   G4 internal error — safe escalateNr#   rB   r+   rH   )rI   rJ   rK   r{   r|   r'   rN   s          r*   _evaluate_G4r   >  s   @g##Ir2667KTRT>'79]^^jj2%zz*@/R!+.?@T?UV!3w>2FGG  ;.2YZZ!%66I  "%88G  "%55d"#)+6JK 
 "#$0Ff)+6IJ  $)+f=   %+*+2k]:`a   gJ.(>@effgsM   7D AD =D D !D 3D D +D <D 	D: D5/D:5D:c           	     N   	 t         j                  | i       j                  dd      }|dk(  rt        ddd      S |j                  d      }||dk(  rt        d	d
d      S t        dd
d      S t        |t              rx|j                  dd      }|j                  dd      }|dk(  s|du rt        dd| d      S |dv rt        d	d| d      S |dv r#t        dd| d|j                  dd             S t        d	dd      S # t
        $ r}t        dd| d      cY d}~S d}~ww xY w) u/   G5: qc_verification — qc_verify.py core gate.r   r   r   r.   z"G5 not required for this task_mode	qc_resultNr   r
   
qc_not_runz!G5 strict: qc_verify not executedzG5: qc not availablerS   r"   passedr	   Tz
qc_status=zG5 qc verification PASSrT   zG5 qc verification WARNrU   r   zG5 qc verification FAIL: reason qc_result_ambiguouszG5: qc result ambiguousr   zG5_exception: u#   G5 internal error — safe escalaterX   )rI   rJ   rK   r   rS   r   rN   s          r*   _evaluate_G5r     sg   !g##Ir2667KTRT>'79]^^JJ{+	!# 7 
  |5KLLi&]]8Y7F]]8T2F6T>#Fj,AC\]]"#Fj,AC\]]**# )/	h0K/LM  F$9;TUU gJ.(>@effgsA   7D $D D ,AD 9D &D 4D 	D$
DD$D$c                   	 t         j                  | i       j                  dd      }|dk(  rt        ddd      S |j                  d      }|t        ddd	      S |d
u rt        ddd      S |du r|dk(  rt        ddd      S t        ddd      S t        ddd      S # t        $ r}t        dd| d      cY d}~S d}~ww xY w)u?   G6: lineage_preservation — parent task lineage sha unchanged.r   r   r   r.   z"G6 not required for this task_modelineage_sha_changedNlineage_not_checkedzG6: lineage sha not checkedFr	   lineage_sha_unchangedzG6 lineage preservation PASSTr   r   zlineage_sha_changed=Truez8G6 lineage preservation FAIL: parent lineage sha changedr
   z8G6 lineage preservation WARN: parent lineage sha changedlineage_indeterminatez#G6: lineage sha state indeterminater   zG6_exception: u#   G6 internal error — safe escalater   )rI   rJ   rK   r   rN   s        r*   _evaluate_G6r     s    g##Ir2667PRVWT>'79]^^$jj)>?&'<>[\\%'(?A_``$&!#.N 
  *J  F$;=bcc gJ.(>@effgs:   7B B B +B B B 	B>$B93B>9B>c                     ~ ~t        ddd      S )uA   G7: actor_attribution — P1-C schema only (not yet implemented).r
   P1_C_NOT_YET_IMPLEMENTEDzMG7 actor_attribution: schema defined, enforcement pending P1-C implementation)r+   )rI   rJ   s     r*   _evaluate_G7r     s     	6"W r,   c                   	 t         j                  | i       j                  dd      }|dk(  rt        ddd      S |j                  d      }|j                  d      }g }g }|du r|j                  d	       n|d
u r|j                  d       |.|j                  d|        |dkD  r|j                  d| d       |sC|!||dk(  rt        ddd      S t        ddd      S t        ddj	                  |      xs dd      S |dk(  r.t        ddj	                  |      ddj	                  |             S t        ddj	                  |      ddj	                  |             S # t
        $ r}t        dd| d       cY d}~S d}~ww xY w)!uD   G8: callback_enforcement — ANU-key cron + envelope ≤3,900 bytes.r   r   r   r.   z"G8 not required for this task_modecallback_registeredenvelope_bytesFcallback_not_registeredTzcallback_registered=TrueNzenvelope_bytes=i<  zenvelope_too_large:z>3900r   r
   callback_not_checkedz,G8 strict: callback enforcement not verifiednot_checkedzG8: not checkedr	   r@   callback_okzG8 callback enforcement PASSr   zG8 callback enforcement FAIL: zG8 callback enforcement WARN: r   zG8_exception: u#   G8 internal error — safe escalate)r#   rB   r+   rC   rG   rH   )rI   rJ   rK   r   r   issuesrL   rN   s           r*   _evaluate_G8r     s   1g##Ir2667PRVWT>'79]^^$jj)>?$45%'MM34 D(!!"<=%!!ON3C"DE$ 3N3C5IJ"*~/EX%'.F 
 $E=:KLL		.):].  X		.)061B0CD 
 IIn%,TYYv->,?@
 	
  gJ.(>@effgs;   7E! BE! E!  E!  2E! 3-E! !	F*E?9F?Fc           
     |   	 | t         vrd} i }t        D ]:  }t        j                  |      }|t	        dd| d      ||<   .	  || |      ||<   < |S # t
        $ r }t	        dd| | d      ||<   Y d}~cd}~ww xY w# t
        $ r3}t        D ci c]  }|t	        dd	| d
       nc c}w c}cY d}~S d}~ww xY w)u@  Evaluate all 8 gates for the given task_mode and inputs.

    Args:
        task_mode: One of the valid task_mode strings (or "UNKNOWN").
        gate_inputs: Dict of gate input values (see module docstring).

    Returns:
        Dict of gate_key → gate_result_dict for all 8 gates.

    Safe-fail: never raises.
    r"   Nr   evaluator_missingz: no evaluatorr   zgate_eval_exception: u.   : evaluation threw exception — safe escalatezevaluate_gates_exception: zsafe escalate)r#   r   _GATE_EVALUATORSrB   r+   rH   )rI   gate_inputsr&   gk	evaluatorrN   s         r*   evaluate_gatesr     s    
N*!I 	B(,,R0I )%1DNF[\r
!*9k!BF2J	  ! !-"/u5$LM"F2J  
  
 Z+EcU)K_]]
 
 	

sT   A A? AA? 	A<A72A? 7A<<A? ?	B;B6B)(B60B;6B;c                   	 d}d}g }| j                         D ]i  \  }}t        |t              r|j                  dd      nd}t        j                  |d      }||kD  r|}|}|g}M||k(  sS|dk\  sY|j                  |       k |dk  ry|dk(  ryd| d	d
j                  |       d}||fS # t        $ r}	dd|	 fcY d}	~	S d}	~	ww xY w)a(  Compute overall_result and rationale from all gate results.

    Worst case wins: ESCALATE > FAIL > WARN > PASS.
    N/A gates are excluded.

    Args:
        gates_result: Dict from evaluate_gates().

    Returns:
        (overall_result: str, rationale: str)

    Safe-fail: never raises.
    r   r	   r&   r   r   )r	   u$   all gates N/A — defaulting to PASS)r	   zall applicable gates PASSzworst_grade=z from gates: z, z* (ESCALATE>FAIL>WARN>PASS worst-case wins)r   zcompute_overall_exception: N)itemsrY   rZ   rB   r   rC   rG   rH   )
gates_resultworst_severityworst_gradeworst_gatesr   gvalr&   sevr(   rN   s
             r*   compute_overallr   D  s   ?$**, 	'HB2<T42HTXXh.eF,,vr*C^#!$$!d&3!8""2&	' AA& 6 ;-}TYY{5K4L M8 9 	 I%% ?8>>>?s6   A(B, +B, 1B, 
B, B, ,	C5C;CCN)r&   rD   r'   rD   r(   rD   returnrZ   )rI   rD   rJ   rZ   r   rZ   )rI   rD   r   rZ   r   rZ   )r   rZ   r   ztuple[str, str])__doc__
__future__r   finish_task_profile_schemar   r   __annotations__r#   r+   rO   r[   ry   r   r   r   r   r   r   r   r   r)   r,   r*   <module>r      s  8 # . " $"&&#+ -#+	 %"&&#+ -#+	 % "&&#+ -#,	  '&#' -#'	  ""#' -#+	  ""#' -#,	  ""#' -#'	{G-) G\L/gdgBagHBgJ#gLgD	3gt $"&&+(+	 %
P*?r,   