
    0i}]                    R   d Z ddlm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ddlmZ ddlmZmZmZmZ ddlZdZeej,                  vrej,                  j/                  de       ddlmZ ddlmZ dd	lmZ d
 ZddZddZ ddZ!d Z"d Z#d Z$	 	 	 	 	 ddZ%d Z& G d d      Z'y)u  
tests/epoch/test_epoch_integration.py

Story 9.10: Module 9 Integration Tests — Full Epoch Run

Verifies the complete 7-phase Nightly Epoch pipeline end-to-end with all
11 EpochRunner dependencies mocked (no real Redis, Postgres, Qdrant, or LLM
calls). Every major code path through EpochRunner is exercised.

Test cases:
  IT1   Full 7-phase happy path — EpochResult has all expected phases
  IT2   Phase execution order: conversation→scar→distill→kg_write→architect→code/arena→tier1
  IT3   knowledge_writer.write() is called with axioms + epoch_id
  IT4   Epoch log entry written with correct schema
  IT5   Lock released after epoch completes normally
  IT6   Lock released even when a phase raises an exception (phase 3 failure)
  IT7   Epistemic analysis (non-ontological) — phases 6a/6b skipped
  IT8   Ontological analysis with arena pass → PR created and pr_url set
  IT9   run_epoch_safe returns None when lock already held
  IT10  EpochScheduler.force_trigger() delegates to runner.run_epoch_safe()
  IT11  Epoch log entry has duration_seconds > 0
  IT12  Full pipeline with empty conversations — still completes gracefully
  IT13  Phase 6a skipped when analysis.bottlenecks is empty (ontological, no bottlenecks)
  IT14  Phase 7a skipped when arena_result.ready_for_pr is False

# VERIFICATION_STAMP
# Story: 9.10
# Verified By: parallel-builder
# Verified At: 2026-02-25T00:00:00Z
# Tests: 14/14
# Coverage: 100%
    )annotationsN)Path)	AsyncMock	MagicMockcallpatchz/mnt/e/genesis-system)EpochRunner)EpochScheduler)EpochResultc                     ddddddddgS )zAReturn two mock Axiom-like dicts for use in distillation results.epoch_2026_02_25_001zAlways verify locks?)idcontent
confidenceepoch_2026_02_25_002zCache invalidation mattersg      ? r       ;/mnt/e/genesis-system/tests/epoch/test_epoch_integration.py_make_mock_axiomsr   A   s&     &2GWZ[%2N^bc r   c                N    t               }| | n	t               |_        d|_        |S )z7Build a MagicMock that looks like a DistillationResult.z3Solid week: 42 sagas, 3 failures. Locking improved.)r   r   axiomsweek_summary)r   results     r   _make_mock_distill_resultr   I   s(    [F$0F6G6IFMOFMr   c                L    t               }| |_        ||ng |_        g |_        |S )z:Build a MagicMock that looks like an ArchitectureAnalysis.)r   scopebottlenecksrecommended_fixes)r   r   analysiss      r   _make_mock_analysisr!   Q   s,    {HHN*5*A;rH!#HOr   c                R    t               }| |_        ||_        ||_        g |_        |S )z1Build a MagicMock that looks like an ArenaResult.)r   	pass_ratepassedready_for_praxiom_violations)r#   r%   arenas      r   _make_mock_arena_resultr(   Z   s,    KEEOEL%EELr   c                 D    t               } d| _        d| _        d| _        | S )z-Build a MagicMock that looks like a PRResult.'https://github.com/genesis/repo/pull/42zepoch-fix-2026_02_25*   )r   pr_urlbranch_name	pr_number)prs    r   _make_mock_pr_resultr0   d   s#    	B9BI+BNBLIr   c                 R    t               } d| _        d| _        d| _        d| _        | S )z5Build a MagicMock that looks like a Tier1EpochResult.      r   )r   kg_axioms_writtenprompt_templates_updatedrules_appendedqdrant_scars_updated)t1s    r   _make_mock_tier1_resultr9   m   s.    	BB"#BBBIr   c                 6    t               } d| _        d| _        | S )z1Build a MagicMock that looks like a CodeProposal.z#core/interceptors/lock_validator.pyzclass LockValidator: pass)r   	file_pathcode_content)proposals    r   _make_mock_proposalr>   w   s    {H>H7HOr   c                   t               }| |j                  _        d|j                  _        t               }t               }d|_        d|_        ddg|_        ||j                  _        t               }t               }	d|	_        g |	_	        |	|j                  _        t               }
t        |      |
j                  _        t               }t               }d|_        d|_        d|_        ||j                  _        t               }t!        ||      |j"                  _        t               }t%               |j&                  _        t               }t)        |rd	nd
|      |j*                  _        t               }t-               |j.                  _        t               }t1               |j2                  _        t               }t               }d|_        d|_        ||j8                  _        t;        ||||
|||||||      S )z
    Create a complete set of 11 mock dependencies for EpochRunner.

    Returns a dict keyed by parameter name for easy EpochRunner construction.
    N   r2   zSession A ran finezSession B failed on lock   zN/mnt/e/genesis-system/KNOWLEDGE_GRAPH/axioms/genesis_evolution_learnings.jsonl)r   r   r   g      ?)r#   r%   z# Genesis Nightly Epochz/tmp/epoch_test.md)lock
aggregatorscar_aggregator	distillerknowledge_writermeta_architectcode_proposershadow_arena
pr_creatortier1_triggerreport_generator)r   acquirereturn_valuereleasetotal_sessionsfailed_tasksconversation_snippets	aggregatetotal_scarsclustersr   distillkg_file_pathqdrant_upsertsjsonl_entrieswriter!   analyzer>   proposer(   evaluate_proposalr0   	create_prr9   applymarkdown_contentr;   generatedict)lock_acquiresanalysis_scopeanalysis_bottlenecksarena_passesr   rB   rC   conv_summaryrD   scar_reportrE   rF   write_resultrG   rH   rI   rJ   rK   rL   
report_objs                       r   _make_all_depsrk      s    ;D -DLL $DLLJ;L"#L !L*>@Z)[L&(4J%kO+KKK-8O*I%>v%FI" {;L pL"#L!"L*6'[N*=(+N'
 KM)<)>M&;L2I%#3!3L""/
 J(<(>J%KM'>'@M$ {J";J/J-7*')%#!#) r   c                |    t               }|j                  |       t        | dz        }t        di |d|i}|||fS )zJCreate an EpochRunner with mocked deps, writing its epoch log to tmp_path.epoch_log.jsonlepoch_log_pathr   )rk   updatestrr	   )tmp_pathoverride_depsdepslog_pathrunners        r   _make_runnerrv      sE    DKK8//0H9499F4!!r   c                  d    e 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)TestFullEpochRunug  
    Integration: Full epoch run with all 11 components wired together via mocks.

    All external I/O is replaced with MagicMock — no Redis, Postgres, Qdrant,
    or LLM calls are made.  The EpochRunner's orchestration logic (phase ordering,
    lock lifecycle, conditional code paths) is verified through call-count checks
    and output inspection.
    c                z   t        |      \  }}}t        j                  |j                  d            }t	        |t
              }|sd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                  t
              rt        j                  t
              ndt        j                  |      dz  }t        t        j                  |            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  }
dd|
iz  }t        t        j                  |            dx}x}}	dD ]  }|j                  }||v }|s t        j                  d|fd||f      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        j                   d| d|j                         dz   d|iz  }t        t        j                  |            dx}} y)uP   IT1: Full 7-phase epoch with mock deps → EpochResult contains expected phases.epoch_2026_02_255assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancer   r   py0py1py2py4N==)z0%(py2)s
{%(py2)s = %(py0)s.epoch_id
} == %(py5)sr~   r   py5assert %(py7)spy7conversation_aggregatescar_aggregateaxiom_distillknowledge_writerG   tier1_updatereport_generatein)z8%(py0)s in %(py4)s
{%(py4)s = %(py2)s.phases_completed
}expected_phaser~   r   r   zExpected phase 'z!' missing from phases_completed: 
>assert %(py6)spy6)rv   asynciorun	run_epochr|   r   @py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanationepoch_id_call_reprcomparephases_completed_format_assertmsg)selfrq   ru   rs   _r   @py_assert3@py_format5@py_assert1@py_assert4@py_format6@py_format8r   @py_format7s                 r   &test_it1_full_epoch_all_phases_presentz7TestFullEpochRun.test_it1_full_epoch_all_phases_present   s9   &x0aV--.@AB&+........z...z......&...&......+...+..........4"44"44444"4444444v444v444444"44444444
 	N &,%<%< >%<<   >%<   v   "   I "   v   &,   I &,   I &=    #>"22S**+-    	r   c                   t        |      \  }}}t        j                  |j                  d            }|j                  }g d}|D cg c]	  }||v s| }	}|	D cg c]  }|j                  |       }
}t        |
      }|
|k(  }|s<t        j                  d|fd|
|f      dt        j                         v st        j                  |
      rt        j                  |
      nd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                  |      dz  }t        j                  d|       d	z   d
|iz  }t        t        j                  |            dx}}yc c}w c c}w )u_   IT2: Phases execute in correct order (conv→scar→distill→kg→architect→tier1→report).rz   r   r   )z0%(py0)s == %(py5)s
{%(py5)s = %(py2)s(%(py3)s)
}indicessortedr~   r   py3r   z#Phases not in expected order. Got: z
>assert %(py7)sr   N)rv   r   r   r   r   indexr   r   r   r   r   r   r   r   r   r   )r   rq   ru   rs   r   r   phasesphase_orderppresentr   r   r   r   r   s                  r   test_it2_phase_execution_orderz/TestFullEpochRun.test_it2_phase_execution_order  s   &x0aV--.@AB((
 *9Q&[199,34q6<<?44 / 	
w/) 	
 	
 	
w/ 	
 	
	6	
 	
   	
 	
 		  	
 	
	6	
 	
  ! 	
 	
 		 ! 	
 	
	6	
 	
  ") 	
 	
 		 ") 	
 	
 		 * 	
 	
  2&:	
 	
 	
 	
 	
 :4s   	G
G
Gc                   t        |      \  }}}t        j                  |j                  d             |d   }|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                  |      t        j                  |      dz  }
t        j                  d      d	z   d
|
iz  }t        t        j                  |            dx}x}x}	}|j                  j                  d   }|d   d   }|d   d   }t!        |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                  t"              rt        j                  t"              ndt        j                  |      dz  }t        t        j                  |            d}d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }t        j                  d|       dz   d|iz  }t        t        j                  |            dx}}y)zNIT3: EpochKnowledgeWriter.write() is called with the axioms list and epoch_id.rz   rF   r3   >=)zM%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.write
}.call_count
} >= %(py7)skw)r~   r   r   r   z)knowledge_writer.write() was never calledz
>assert %(py9)spy9Nr   z*First arg to write() should be axioms listz7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}r|   
axioms_arglistr}   r   )z%(py0)s == %(py3)sepoch_id_argr~   r   z/Second arg to write() should be epoch_id, got: 
>assert %(py5)sr   )rv   r   r   r   rZ   
call_countr   r   r   r   r   r   r   r   r   call_args_listr|   r   )r   rq   ru   rs   r   r   r   r   @py_assert6@py_assert5r   @py_format10	call_argsr   r   r   @py_assert2@py_format4r   s                      r    test_it3_knowledge_writer_calledz1TestFullEpochRun.test_it3_knowledge_writer_called"  s/   &x0aF$$%789$%xxTx""TaT"a'TTT"aTTTTTTrTTTrTTTxTTT"TTTaTTT)TTTTTTTT HH++A.	q\!_
 |A*d+Y+YY-YYYYYYYzYYYzYYYYYY*YYY*YYYYYYdYYYdYYY+YYYYYY1 	
|11 	
 	
|1 	
 	
	6	
 	
   	
 	
 		  	
 	
 		  2 	
 	
  >l^L	
 	
 	
 	
 	
r   c                   t        |      \  }}}t        j                  |j                  d             t	        |      }|j
                  } |       }|st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}|j                  d      j                         j!                         }	t#        |	      }
d	}|
|k\  }|st        j$                  d
|fd|
|f      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        j                  d      dz   d|iz  }t        t        j                  |            dx}
x}}t'        j(                  |	d         }g d}|D ]  }||v }|st        j$                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }t        j                  d| d|       dz   d|iz  }t        t        j                  |            d} |d   }d}||k(  }
|
slt        j$                  d|
fd||f      t        j                  |      t        j                  |      d z  }d!d"|iz  }t        t        j                  |            dx}x}
}|d#   }t+        |t,              }|sd$d%t        j                         v st        j                  t*              rt        j                  t*              nd%t        j                  |      d&t        j                         v st        j                  t,              rt        j                  t,              nd&t        j                  |      d'z  }t        t        j                  |            dx}}|d(   }t+        |t.              }|sd$d%t        j                         v st        j                  t*              rt        j                  t*              nd%t        j                  |      d)t        j                         v st        j                  t.              rt        j                  t.              nd)t        j                  |      d'z  }t        t        j                  |            dx}}y)*zKIT4: Epoch log entry is written to epoch_log.jsonl with the correct schema.rz   zEpoch log file was not createdzC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}log_filer   Nutf-8encodingr3   r   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)slenlines)r~   r   r   r   zEpoch log file is emptyz
>assert %(py8)spy8)	r   	timestampr   axioms_countr,   tier1_updatesr   shadow_pass_rateduration_secondsr   )z%(py0)s in %(py2)s
field_nameentry)r~   r   zRequired field 'z ' missing from epoch log entry: z
>assert %(py4)sr   r   r   )z%(py1)s == %(py4)sr   r   zassert %(py6)sr   r   z5assert %(py5)s
{%(py5)s = %(py0)s(%(py2)s, %(py3)s)
}r|   r   r   r   int)rv   r   r   r   r   existsr   r   r   r   r   r   r   r   	read_textstrip
splitlinesr   r   jsonloadsr|   r   r   )r   rq   ru   rs   rt   r   r   r   r   r   r   r   r   r   @py_format9r   required_fieldsr   @py_format3@py_assert0r   s                        r   test_it4_epoch_log_schemaz*TestFullEpochRun.test_it4_epoch_log_schema8  s   !-h!7hF$$%789>B B BB"BBBBBBBxBBBxBBBBBB BBBBBB""G"4::<GGI5z9Q9zQ999zQ999999s999s99999959995999z999Q999 99999999

59%

 * 	J&  :  v     I   v   "'  I "'    #:,.NugV    	
 Z 6$66 $66666 $6666 666$66666666 23:z3T::::::::z:::z:::3::::::T:::T::::::::::/5z/55555555z555z555/5555555555555555555r   c                    t        |      \  }}}t        j                  |j                                |d   }|j                  j                          y)zBIT5: lock.release() is called after a normal successful epoch run.rB   N)rv   r   r   run_epoch_saferO   assert_called_once)r   rq   ru   rs   r   rB   s         r   .test_it5_lock_released_after_normal_completionz?TestFullEpochRun.test_it5_lock_released_after_normal_completion^  s@    &x0aF))+,F|'')r   c                   t               }t        d      |d   j                  _        t	        |dz        }t        di |d|i}t        j                  |j                               }|d   j                  j                          |d   j                  j                          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)zGIT6: lock.release() is called even when phase 3 (axiom_distill) raises.zGemini API downrE   rm   rn   rB   Nis notz%(py0)s is not %(py3)sr   r   assert %(py5)sr   r   )rk   RuntimeErrorrV   side_effectrp   r	   r   r   r   rM   r   rO   r   r   r   r   r   r   r   r   )
r   rq   deps_overridert   ru   r   r   r   r   r   s
             r   'test_it6_lock_released_on_phase_failurez8TestFullEpochRun.test_it6_lock_released_on_phase_failurej  s    &(9EFW9Xk"**6x"334F}FXF V2245 	f%%88:f%%88: "!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!r   c                h   t        |fi t        d      \  }}}t        j                  |j	                  d             |d   j
                  j                          |d   j                  j                          |d   j                  j                          |d   j                  j                          y)	zWIT7: When analysis.scope == 'epistemic', code_proposer and shadow_arena are NOT called.	epistemic)rd   rz   rH   rI   rJ   rK   N)rv   rk   r   r   r   r\   assert_not_calledr]   r^   r_   r   )r   rq   ru   rs   r   s        r   *test_it7_epistemic_scope_skips_code_phasesz;TestFullEpochRun.test_it7_epistemic_scope_skips_code_phases  s    &x^>Q\3]^aF$$%789_%%779^..@@B\$$668 	_##668r   c                   t               }d|_        d|_        t        d|gd      }t	        |dz        }t        di |d|i}t        j                  |j                  d            }|d	   j                  j                          |d
   j                  j                          |d   j                  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  }
d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  }
d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  }
d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  }
dd|
iz  }t)        t        j*                  |            dx}x}}y)uJ   IT8: Ontological scope + arena pass → PR created, pr_url in EpochResult.zLocking contention   ontologicalTrd   re   rf   rm   rn   rz   rH   rI   rJ   r*   r   )z.%(py2)s
{%(py2)s = %(py0)s.pr_url
} == %(py5)sr   r   r   r   Ncode_proposer   z8%(py1)s in %(py5)s
{%(py5)s = %(py3)s.phases_completed
}r   r   r   	pr_creater   )r   description	frequencyrk   rp   r	   r   r   r   r\   r   r]   r^   r,   r   r   r   r   r   r   r   r   r   )r   rq   
bottleneckall_depsrt   ru   r   r   r   r   r   r   r   r   s                 r   /test_it8_ontological_with_arena_pass_creates_prz@TestFullEpochRun.test_it8_ontological_with_arena_pass_creates_pr  s~   [
!5
 
!(",

 x"334AxAAV--.@AB 	!))<<> 22EEG((;;= }}I II} IIIII} IIIIIIIvIIIvIII}III IIIIIIII 8!8!88~!88888~!8888~888888888888!888888888!8!88~!88888~!8888~888888888888!888888885f555{55555{5555{555555f555f55555555555r   c                   t        d      }t        |dz        }t        di |d|i}t        j                  |j                               }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	z  }t        j                  d
      dz   d|iz  }	t        t        j                  |	            dx}}|d   j                  j!                          |d   j"                  j!                          |d   j$                  j!                          y)zPIT9: run_epoch_safe() returns None without running any phases when lock is held.F)rc   rm   rn   Nis)z%(py0)s is %(py3)sr   r   z$Expected None when lock not acquiredr   r   rC   rE   rF   r   )rk   rp   r	   r   r   r   r   r   r   r   r   r   r   r   r   rS   r   rV   rZ   )
r   rq   r  rt   ru   r   r   r   r   r   s
             r   3test_it9_run_epoch_safe_returns_none_when_lock_heldzDTestFullEpochRun.test_it9_run_epoch_safe_returns_none_when_lock_held  s    !6x"334AxAAV2245Ev~EEEvEEEEEEvEEEvEEEEEEEEEEEEE 	((::<%%779#$**<<>r   c                    t               }t        d      |_        t        |dz        }t	        ||      }t        j                  |j                                |j                  j                          y)zSIT10: EpochScheduler.force_trigger() delegates directly to runner.run_epoch_safe().N)rN   zevents.jsonl)events_log_path)	r   r   r   rp   r
   r   r   force_triggerr   )r   rq   mock_runner
events_log	schedulers        r   6test_it10_scheduler_force_trigger_calls_run_epoch_safezGTestFullEpochRun.test_it10_scheduler_force_trigger_calls_run_epoch_safe  sX    k%.D%A"N23
";
K	I++-.""557r   c                &   t        |      \  }}}t        j                  |j                  d             t	        |      }t        j                  |j                  d      j                         j                         d         }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndd	z  }	d
d|	iz  }
t!        t        j"                  |
            dx}}|d   }d}||k\  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j$                  d|d          dz   d|iz  }t!        t        j"                  |            dx}x}}|d   }t&        t(        f}t+        ||      }|sddt        j                         v st        j                  t*              rt        j                  t*              ndt        j                  |      t        j                  |      t        j                  |      dz  }t!        t        j"                  |            dx}x}}y)z3IT11: Epoch log entry records duration_seconds > 0.rz   r   r   r   r   r   )z%(py1)s in %(py3)sr   )r   r   r   r   Nr   r   )z%(py1)s >= %(py4)sr   z.duration_seconds should be non-negative, got: r   r   z5assert %(py6)s
{%(py6)s = %(py0)s(%(py2)s, %(py4)s)
}r|   )r~   r   r   r   )rv   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   floatr|   )r   rq   ru   rs   rt   r   r   r   r   r   r   r   r   r   r   r   s                   r   %test_it11_epoch_log_duration_positivez6TestFullEpochRun.test_it11_epoch_log_duration_positive  s   !-h!7hF$$%789>

8--w-?EEGRRTUWXY!*!U****!U***!******U***U*******'( 	
A 	
(A- 	
 	
(A 	
 	
 		 ) 	
 	
 		 -. 	
 	
  =UCU=V<WX	
 	
 	
 	
 	
   23Bc5\Bz3\BBBBBBBBzBBBzBBB3BBB\BBBBBBBBBBr   c                "   t        g       }t               }d|_        d|_        g |_        ||d   j
                  _        t               }g |_        d|_        ||d   j                  _        t        |dz        }t        di |d|i}t        j                  |j                  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}	}t/        |t0              }|sd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&                  t0              rt        j(                  t0              ndt        j(                  |      dz  }t+        t        j,                  |            d	}|j                  }	g }|	|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  }dd|iz  }t+        t        j,                  |            d	x}	x}}|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  }dd|iz  }t+        t        j,                  |            d	x}	x}}d}|j2                  }||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  }dd|iz  }t+        t        j,                  |            d	x}x}}d}|j2                  }||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  }dd|iz  }t+        t        j,                  |            d	x}x}}y	) zFIT12: Pipeline completes gracefully even when conversations are empty.)r   r   rC    rE   rm   rn   rz   Nr   r   r   r   r   r   r{   r|   r   r}   r   )z.%(py2)s
{%(py2)s = %(py0)s.axioms
} == %(py5)sr   r   r   )z4%(py2)s
{%(py2)s = %(py0)s.week_summary
} == %(py5)sr   r   r   r   r   r   )rk   r   rP   rQ   rR   rS   rN   r   r   rV   rp   r	   r   r   r   r   r   r   r   r   r   r   r   r|   r   r   )r   rq   r  
empty_convempty_distillrt   ru   r   r   r   r   r   r   r   r   r   r   s                    r   1test_it12_empty_conversations_graceful_completionzBTestFullEpochRun.test_it12_empty_conversations_graceful_completion  sV   !, [
$%
!"#
+-
(8B((5 "!%'"5B%%2x"334AxAAV--.@AB "!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!&+........z...z......&...&......+...+..........}}""}""""}""""""v"""v"""}""""""""""""(b("b(((("b((((((v(((v((("(((b((((((( (B6+B+BB'+BBBBB'+BBBB'BBBBBB6BBB6BBB+BBBBBBBB ;F$;$;; $;;;;; $;;;; ;;;;;;F;;;F;;;$;;;;;;;;r   c                   t        dg       }t        |dz        }t        di |d|i}t        j                  |j                  d            }|d   j                  j                          |d   j                  j                          |d   j                  j                          |j                  }d	}||u }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |      dz  }	dd|	iz  }
t#        t        j$                  |
            d	x}x}}|d   j&                  j)                          y	)uY   IT13: Ontological analysis with empty bottlenecks → code_proposer.propose() NOT called.r   )rd   re   rm   rn   rz   rH   rI   rJ   Nr  z.%(py2)s
{%(py2)s = %(py0)s.pr_url
} is %(py5)sr   r   r   r   rK   r   )rk   rp   r	   r   r   r   r\   r   r]   r^   r,   r   r   r   r   r   r   r   r   r_   r   )r   rq   r  rt   ru   r   r   r   r   r   r   s              r   7test_it13_ontological_no_bottlenecks_skips_code_proposezHTestFullEpochRun.test_it13_ontological_no_bottlenecks_skips_code_propose  s   !(!#
 x"334AxAAV--.@AB 	!));;= 22DDF((::< }}$$}$$$$}$$$$$$v$$$v$$$}$$$$$$$$$$ 	!''::<r   c                J   t               }d|_        d|_        t        d|gd      }t	        |dz        }t        di |d|i}t        j                  |j                  d            }|d	   j                  j                          |d
   j                  j                          |d   j                  j                          |j                  }d}||u }	|	st        j                   d|	fd||f      dt#        j$                         v st        j&                  |      rt        j(                  |      ndt        j(                  |      t        j(                  |      dz  }
dd|
iz  }t+        t        j,                  |            dx}x}	}|d   j.                  j                          y)zTIT14: When arena_result.ready_for_pr is False, pr_creator.create_pr() is NOT called.zTimeout in saga routing   r   Fr   rm   rn   rz   rH   rI   rJ   Nr  r  r   r   r   r   rK   r   )r   r  r  rk   rp   r	   r   r   r   r\   r   r]   r^   r   r,   r   r   r   r   r   r   r   r   r_   )r   rq   r  r  rt   ru   r   r   r   r   r   r   s               r   &test_it14_arena_fail_skips_pr_creationz7TestFullEpochRun.test_it14_arena_fail_skips_pr_creation%  s=   [
!:
 
!(",

 x"334AxAAV--.@AB 	!))<<> 22EEG 	((::< }}$$}$$$$}$$$$$$v$$$v$$$}$$$$$$$$$$ 	!''::<r   N)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r  r	  r  r  r  r  r  r   r   r   rx   rx      sQ    6
6
, 6L*",
9 6B?&
8 C&<H=4=r   rx   )N)r   N)r   T)Tr   NFN)(r"  
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r   r   systempfilepathlibr   unittest.mockr   r   r   r   pytestGENESIS_ROOTpathinsertcore.epoch.epoch_runnerr	   core.epoch.epoch_schedulerr
   !core.epoch.epoch_report_generatorr   r   r   r!   r(   r0   r9   r>   rk   rv   rx   r   r   r   <module>r3     s   B #     
   ; ;  'sxxHHOOA|$ 0 5 9 Nb"b= b=r   