
    4j(/                     b   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
ddlZe
j                  j                  e
j                  j                  e
j                  j                  e      dd            Ze
j                  j                  edd      Ze
j                  j                  ed      Ze
j                  j                  ed      ZdZe
j                  j                  ed	d
      Zg dZd Zd Z G d dej4                        Z G d dej4                        Zedk(  r ej<                  d       yy)u7  Regression — task-2553+35 TRACK C3: policy_profile_engine dry-run application.

Phase-B contract:
  * C1 engine (anu_v3/policy_profile_engine) PRESENT  -> run dry-run against the
    4 task-2553 targets and assert engine-derived gate/HOLD/completion-packet
    schema matches the Phase-A read-only baseline. NO real merge / GitHub write /
    thread resolve is ever performed (dry-run only).
  * C1 engine ABSENT -> skip the engine-consuming assertions and assert the
    deferral is recorded as the explicit terminal status DEFERRED_PENDING_C1
    (NOT HOLD, NOT FAIL) with a next_action.

Phase-A baseline assertions always run (engine-independent): they re-derive the
expected gate/HOLD/packet keys from the existing task-2553 actual-result events
read-only and assert the comparison artifact encodes them faithfully.
    Nz..memoryeventsz$task-2553+35.dry-run-comparison.jsonztask-2553+35.result.jsonzanu_v3.policy_profile_engineanu_v3zpolicy_profile_engine.py)PR#128 clean replacement merge PR#129 test-only hardening mergeGemini thread resolve*post-merge smoke harness artifact closeoutc                 t    t        | dd      5 }t        j                  |      cd d d        S # 1 sw Y   y xY w)Nrzutf-8)encoding)openjsonload)pathfhs     T/home/jay/workspace/tests/regression/test_policy_profile_engine_dryrun_2553plus35.py_loadr   %   s0    	dC'	* byy}  s   .7c                      t         j                  j                  t              sy	 t        j
                  j                  t              duS # t        t        t        f$ r Y yw xY w)u:   C1 engine presence probe — import spec AND file on disk.FN)osr   isfileENGINE_PATH	importlibutil	find_specENGINE_MODULEImportError
ValueErrorModuleNotFoundError     r   _engine_presentr!   *   sN    77>>+&~~''6dBB%89 s   $A A"!A"c                   D    e Zd ZdZed        Zd Zd Zd Zd Z	d Z
d Zy	)
PhaseABaselineTestu#   Engine-independent — always runs.c                 ,    t        t              | _        y N)r   
COMPARISONcmpclss    r   
setUpClasszPhaseABaselineTest.setUpClass7   s    
#r    c                     | j                  | j                  d   d       | j                  | j                  d   d       | j                  d| j                         | j                  d| j                         y )Ntaskztask-2553+35task_md_sha256@0a0415868cb288a7ad2678022c2c2d3c690f8914bda559eec655cf9acc1cd799phase_aphase_b)assertEqualr'   assertIn)selfs    r   test_comparison_artifact_schemaz2PhaseABaselineTest.test_comparison_artifact_schema;   s_    &)>:HH%&N	
 	i*i*r    c                 ~    | j                   d   d   D cg c]  }|d   	 }}| j                  |t               y c c}w )Nr/   targetstarget)r'   r1   TARGETS)r3   tgots      r    test_phase_a_covers_four_targetsz3PhaseABaselineTest.test_phase_a_covers_four_targetsD   s=    $(HHY$7	$BCqq{CCg& Ds   :c                 F   | j                   d   d   D ]  }| j                  d||d          | j                  d|d   |d          | j                  d||d          | j                  d||d          | j                  d||d          | j                  d	|d   |d           y )
Nr/   r6   profile_selectionr7   	goal_typeexpected_gateexpected_hold!expected_completion_packet_schemaactual_terminal_status)r'   r2   )r3   r9   s     r   5test_phase_a_each_target_has_profile_gate_hold_packetzHPhaseABaselineTest.test_phase_a_each_target_has_profile_gate_hold_packetH   s    )$Y/ 
	AMM-q!H+>MM+q)<'=q{KMM/1ak:MM/1ak:MM3Q( MM(!O*<ak
	r    c                    | j                   d   d   D ci c]  }|d   |
 }}t        t        j                  j	                  t
        d            }| j                  |d   d       | j                  |d   d   d	   d       t        t        j                  j	                  t
        d
            }| j                  |d   d       | j                  |d   d          | j                  |d   d   d	   d       t        t        j                  j	                  t
        d            }| j                  |d   d       | j                  |d   d          | j                  |d   d   d	   d       t        t        j                  j	                  t
        d            }| j                  |d   d       | j                  |d          | j                  |d   d   d	   d       yc c}w )z|Re-derive the actual terminal status from the source events
        read-only and assert the baseline encodes it faithfully.r/   r6   r7   task-2553+12.result.jsonstatusHOLD_FOR_CHAIRr   r@   rB   ztask-2553+26.result.jsonoutcomeCOMPLETE_MERGEDconsolidated_summary_99_hold_for_chairr   ztask-2553+11.result.jsonfinal_statuszERESOLVED_THREAD__MERGE_READY (merge NOT performed; chair packet only)scope_compliancehold_triggeredr   RESOLVED_THREAD__MERGE_READYtask-2553+13.result.jsonDONEholdr	   N)r'   r   r   r   joinEVENTSr1   assertFalse)r3   r9   	by_targetplus12plus26plus11plus13s          r   2test_phase_a_baseline_matches_actual_result_eventszEPhaseABaselineTest.test_phase_a_baseline_matches_actual_result_eventsU   s    %)HHY$7	$B
 AhKN
	 
 rww||F,FGH)+;<67H( 		
 rww||F,FGH	*,=>+,-?@	
 	89/J( 		
 rww||F,FGH>"S	
 	 234DEF-.?( +		
 rww||F,FGH)62(BC&( 		
S
s   Gc                    | j                   d   }| j                  |d   d       | j                  |d   d       | j                  |d   d       | j                  |d   d       | j                  |d   d       | j                  |d          y )	Ndry_run_invariants
real_merger   real_github_writereal_thread_resolvec1_core_modified existing_2553_artifacts_modifiedcontamination)r'   r1   rU   )r3   invs     r   .test_dry_run_invariants_zero_real_side_effectszAPhaseABaselineTest.test_dry_run_invariants_zero_real_side_effects   s    hh+,\*A.011523Q7/0!4?@!D_-.r    c                     dD ]I  \  }}}t        t        j                  j                  t        |            }| j                  ||   ||       K y)z|Phase-A is read-only: source events must still parse and keep
        their terminal markers (no mutation introduced by C3).))rE   rF   rG   )rP   rF   rQ   N)r   r   r   rS   rT   r1   )r3   namekeyvaldocs        r   'test_source_events_unmodified_read_onlyz:PhaseABaselineTest.test_source_events_unmodified_read_only   sJ    
 	2ND#s VT23CSXsD1	2r    N)__name__
__module____qualname____doc__classmethodr*   r4   r;   rC   r[   re   rk   r   r    r   r#   r#   4   s6    -$ $+'1
f/2r    r#   c                   ,    e Zd ZdZed        Zd Zd Zy)PhaseBEngineConsumingTestu:   Engine-consuming — dry-run only, never real merge/write.c                 J    t        t              | _        t               | _        y r%   )r   r&   r'   r!   presentr(   s    r   r*   z$PhaseBEngineConsumingTest.setUpClass   s    
#%'r    c                 6   | j                   r| j                  d       | j                  d   }| j                  |d   d       | j	                  |d          | j                  |d   d       | j                  |d          | j	                  | j                  d          t        j                  j                  t              rZt        t              }| j                  |d	   d       | j                  |d	   d
       | j                  |j                  d             y y )Nu-   C1 engine present — handled by dry-run testr0   stateDEFERRED_PENDING_C1executedrG   next_actionhold_for_chairrF   )HOLDFAIL)rt   skipTestr'   r1   rU   assertNotEqual
assertTruer   r   r   RESULTr   assertNotInget)r3   pbress      r   (test_phase_b_deferred_when_engine_absentzBPhaseBEngineConsumingTest.test_phase_b_deferred_when_engine_absent   s    <<MMIJXXi G&;<J(BwK)9:=)*"23477>>&!-CS],ABS],<=OOCGGM23	 "r    c           	         | j                   s| j                  d       t        j                  t              }| j                  t        |d      xr t        |d      d       |j                  }|j                  }|j                  }t        j                  j                  t        dd      }| j                  t              5   |ddd	i
       ddd       | j                   d   d   D ci c]  }|d   |
 }}|j#                         D ]  \  }}	|	d   }
|
j%                  d      }t'        |
j%                  d            xr |du}d|dd  d| d|xs dig dd}|r ||      }| j)                  |d   |d   |        |||      }| j+                  |j,                  d| d       | j                  t        |d      |       | j                  t        |d      |       | j/                  |j0                  t2        |       | j/                  |j4                  t2        |       | j)                  t7        t9        |j:                        t9        |j<                        z        g | d       g| j                  |      5 } | ||      |       ddd       | j                  j>                  j@                  | d         y# 1 sw Y   xY wc c}w # 1 sw Y   HxY w)!u  task-2553+36 TRACK C PHASE-B RECONCILIATION — C3 harness corrected to
        the C1 *settled* canonical API (task-2553+33 ACCEPT).

        C1 canonical contract (회장 verbatim, 변경 불가):
          parse_goal_request(obj, *, schema_dir) ->
          resolve_policy(goal_request, *, profile_json_dir, ...) -> PolicyResolution

        The pre-+36 contract (resolve_policy(goal_type=..., boundary=...) echoing a
        historical *runtime terminal status*) was the documented C1<->C3 API
        mismatch: the settled engine is a PURE CONTRACT DERIVER. It returns
        PolicyResolution.status in {RESOLVED, HOLD_FOR_CHAIR} OR fail-closes with
        PolicyEngineError — it never replays the historical runtime terminal
        status, and never performs a real merge / GitHub write / thread resolve.

        Reconciled dry-run contract (in-memory only, zero side effects):
          * target WITH a real policy_profile instance -> canonical
            parse_goal_request -> resolve_policy(goal_request, profile_json_dir=...)
            succeeds; PolicyResolution exposes gate / hold / completion-packet /
            evidence schema; status in {RESOLVED, HOLD_FOR_CHAIR}.
          * target WITHOUT a profile instance -> the canonical engine
            DETERMINISTICALLY fail-closes (PolicyEngineError) — the correct
            dry-run outcome, NOT an engine defect and NOT a real side effect.
          * the forbidden API resolve_policy(goal_type=..., boundary=...) MUST
            raise (regression §6.2).
        u@   C1 engine absent — Phase-B DEFERRED_PENDING_C1 (not HOLD/FAIL)parse_goal_requestresolve_policyu_   C1 settled canonical API parse_goal_request/resolve_policy 부재 (contract drift → §9 HOLD)r   policy_profilesxdry_runT)r>   boundaryNr/   r6   r7   r=   expected_policy_profile profile_instance_present_in_repozdryrun-2553p36-   zdry-run application: rg   
__absent__)r   no_real_mergeno_github_write)goal_idgoal_statementpolicy_profiler   r   )profile_json_dir)RESOLVEDrG   z): canonical status out of contract domaingatehold_conditionsu1   : allowed∩forbidden 누수 (fail-closed 위반)z1: fail-closed PolicyEngineError must carry a code)!rt   r}   r   import_moduler   r   hasattrr   r   PolicyEngineErrorr   r   rS   	REPO_ROOTassertRaises	TypeErrorr'   itemsr   boolr1   r2   rF   assertIsInstancecompletion_packet_schemadictevidence_schemasortedsetallowed_actionsforbidden_actions	exceptioncode)r3   enginer   r   r   profile_dirr9   baselinetgtbaseselprofile_namert   goal_requestgrr   ctxs                    r   ,test_engine_dry_run_matches_phase_a_baselinezFPhaseBEngineConsumingTest.test_engine_dry_run_matches_phase_a_baseline   s   4 ||MMR
 ((7F01 2 01,	
 $66.."44ggll9h8IJ y) 	FSIt3DE	F -1HHY,?	,JKqAhKNKK!) ,	IC*+C77#<=L377#EFG D(  -S"XJ7$9#"?#)<+G<"HK	L '5  Jj1I3O$R+FJJ2eDE V 4c:-> ?E%%c&B&BD#N%%c&9&94E  3s223c#:O:O6PPQeLM &&'89 S"*<8)4
 MM&&eLMS,			F 	F LJ s   ?K(K?KKK 	N)rl   rm   rn   ro   rp   r*   r   r   r   r    r   rr   rr      s"    D( (4]r    rr   __main__   )	verbosity)ro   builtins@py_builtins_pytest.assertion.rewrite	assertionrewrite
@pytest_arimportlib.utilr   r   r   unittestr   abspathrS   dirname__file__r   rT   r&   r   r   r   r8   r   r!   TestCaser#   rr   rl   mainr   r    r   <module>r      s        	 GGOOBGGLL)BD$OP		i8	4WW\\&"HI
	f8	9.ggll9h0JK
e2** e2Pt 1 1 tn zHMMA r    