
    &iY7                       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Zeej                  vrej                  j                  de       ddlmZmZmZmZ dd	 	 	 	 	 	 	 d9dZd:d;d	Z G d
 d      Z G d d      Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'd Z(d Z)e*dk(  rddl+Z+d efd!efd"efd#efd$efd%efd&efd'e fd(e!fd)e"fd*e#fd+e$fd,e%fd-e&fd.e'fd/e(fd0e)fgZ,dZ- e.e,      Z/e,D ]  \  Z0Z1	  e1         e2d1e0        e-d2z  Z-  e2d5e- d6e/ d7       e-e/k(  r	 e2d8       y ejl                  d2       yy# e3$ r)Z4 e2d3e0 d4e4         e+jj                          Y dZ4[4zdZ4[4ww xY w)<u  
tests/track_b/test_story_9_05.py

Story 9.05: AxiomDistiller — Gemini Pro Weekly Distillation

Black Box Tests (BB):
    BB1  Mock Gemini returns 7 axioms → 7 axioms in result
    BB2  Axioms with confidence < 0.6 filtered out (10 axioms, 3 below → 7 returned)
    BB3  Axiom ID format matches epoch_YYYY_MM_DD_NNN pattern
    BB4  No client → empty DistillationResult (no exception)

White Box Tests (WB):
    WB1  model_name defaults to "gemini-pro" (not Flash)
    WB2  JSON parse failure → empty DistillationResult (not exception)
    WB3  week_summary extracted from LLM response
    WB4  CONFIDENCE_THRESHOLD == 0.6

ALL tests use mock gemini_client. No real LLM calls.
    )annotationsNz/mnt/e/genesis-systemAxiomDistillerAxiomDistillationResultCONFIDENCE_THRESHOLD
2026_02_25)	date_hintc               0    d| d| dd|  d|d| dgdS )z5Build a single axiom dict as the LLM would return it.epoch__03dzAxiom content number 
operationssaga_idcontentcategory
confidencesource_saga_ids )idxr   r
   s      6/mnt/e/genesis-system/tests/track_b/test_story_9_05.py_make_axiom_payloadr   5   s?     yk3s),*3%0  #C9-.     c                H    | |d}t        j                  |      dfd}|S )zFReturn a callable that acts like a Gemini client returning fixed JSON.)axiomsweek_summaryc                    S Nr   )promptraw_jsons    r   _clientz_mock_client.<locals>._clientJ   s    r   r!   strreturnr%   jsondumps)axiom_dictsr   payloadr#   r"   s       @r   _mock_clientr,   E   s'    $lCGzz'"H Nr   c                  .    e Zd ZdZ	 	 	 d	 	 	 	 	 	 	 ddZy)_FakeConversationsz6Minimal WeeklyConversationSummary-alike for injection.Nc                6    || _         || _        |xs g | _        y r    )total_sessionsfailed_tasksconversation_snippets)selfr0   r1   snippetss       r   __init__z_FakeConversations.__init__S   s      -(%-^"r   )      N)r0   intr1   r8   r4   zlist[str] | Noner&   None__name__
__module____qualname____doc__r5   r   r   r   r.   r.   P   s;    @  %)	44 4 #	4
 
4r   r.   c                      e Zd ZdZdddZy)
_FakeScarsz'Minimal ScarReport-alike for injection.Nc                    |xs g | _         y r    )clusters)r3   rB   s     r   r5   z_FakeScars.__init__a   s     Br   r    )rB   zlist | Noner&   r9   r:   r   r   r   r@   r@   ^   s
    1'r   r@   c                 &   t        dd      D  cg c]  } t        | d       }} t        t        |            }|j	                  t               t                     }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                   }t#        |      }d}||k(  }	|	s6t        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                  |      t        j                  |      dz  }
t        j&                  dt#        |j                                dz   d|
iz  }t        t        j                  |            d
x}x}x}	}|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
}& y
c c} w )uQ   BB1: Mock Gemini returns 7 axioms (all confidence >= 0.6) → 7 axioms in result.r7      g      ?gemini_client5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstanceresultr   py0py1py2py4N   ==zL%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.axioms
})
} == %(py8)slenrK   rL   py3py5py8zExpected 7 axioms, got 
>assert %(py10)spy10axiomr   )ranger   r   r,   distillr.   r@   rH   r   @py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanationr   rS   _call_reprcompare_format_assertmsgr   )ir*   	distillerrI   @py_assert3@py_format5@py_assert2@py_assert4@py_assert7@py_assert6@py_format9@py_format11rZ   s                r   test_bb1_seven_axioms_returnedrp   j   s7   9>q!EA&q$/EKE\+-FGI13Z\BFf011111111:111:111111f111f111111011101111111111}}R3}RR"RRRRRRRRR3RRR3RRRRRRvRRRvRRR}RRRRRRRRR&=c&-->P=Q$RRRRRRRR (%''''''''z'''z''''''%'''%'''''''''''''''''''( Fs   Pc                    t        dd      D  cg c]  } t        | d       }} t        dd      D  cg c]  } t        | d       }} ||z   }t        t        |            }|j	                  t               t                     }|j                  }t        |      }d}||k(  }	|	s6t        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                  |      t        j                  |      dz  }
t        j                  dt        |j                               dz   d|
iz  }t!        t        j"                  |            dx}x}x}	}|j                  D ]  }|j$                  }|t&        k\  }|st        j                  d|fd|t&        f      dt        j                         v st        j                  |      rt        j                  |      nd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}} yc c} w c c} w )u<   BB2: 10 axioms, 3 below confidence threshold → 7 returned.r7   rD   g?   g      ?rE   rO   rP   rR   rS   rI   rT   z=Expected 7 axioms after filtering 3 low-confidence ones, got rX   rY   N)>=)z2%(py2)s
{%(py2)s = %(py0)s.confidence
} >= %(py4)srZ   r   rK   rM   rN   zassert %(py6)spy6)r[   r   r   r,   r\   r.   r@   r   rS   r_   rd   r]   r^   r`   ra   re   rb   rc   r   r   )rf   highlowr*   rg   rI   rj   rk   rl   rm   rn   ro   rZ   @py_assert1rh   ri   @py_format7s                    r   'test_bb2_low_confidence_axioms_filteredrz   w   s?    381+>Q4(>D>16q"
>Aq$'
>C
>*K\+-FGI13Z\BF}} 3}  "                                   "#    HFMMHZG[\       87#77777#7777777u777u777777777#7777#777777778 ?
>s
   K7K<c                 L   dddddgdg} t        t        |             }|j                  t               t	                     }|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                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}|j
                  d   j                  }	t!        j"                  d      }
|
j$                  } ||	      }|st        j&                  d|	 d      dz   dt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      dt        j                         v st        j                  |	      rt        j                  |	      ndt        j                  |      dz  }t        t        j                  |            dx}}y)z:BB3: Axiom ID format matches epoch_YYYY_MM_DD_NNN pattern.epoch_2026_02_25_001zVerify infra before buildinfrastructure?saga_001r   rE   r7   rP   rR   rS   rI   rT   assert %(py10)srY   Nr   z^epoch_\d{4}_\d{2}_\d{2}_\d{3}$z
Axiom ID 'z-' does not match pattern epoch_YYYY_MM_DD_NNNzI
>assert %(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.match
}(%(py3)s)
}patternaxiom_idrK   rM   rU   rV   )r   r,   r\   r.   r@   r   rS   r_   rd   r]   r^   r`   ra   rb   rc   r   recompilematchre   )r*   rg   rI   rj   rk   rl   rm   rn   ro   r   r   rx   @py_format6s                r   test_bb3_axiom_id_formatr      s    )2( *|	
K \+-FGI13Z\BF}}"3}""""""""""""3"""3""""""v"""v"""}"""""""""""""}}Q""Hjj;<G== =" "   XJKL                   "    "    #     r   c                    t        d      } | j                  t               t                     }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                  }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}}y)uE   BB4: No client → empty DistillationResult with no exception raised.NrE   rG   rH   rI   r   rJ   rP   z.%(py2)s
{%(py2)s = %(py0)s.axioms
} == %(py5)srK   rM   rV   assert %(py7)spy7 z4%(py2)s
{%(py2)s = %(py0)s.week_summary
} == %(py5)sr   r\   r.   r@   rH   r   r]   r^   r_   r`   ra   rb   rc   r   rd   r   rg   rI   rh   ri   rx   rk   r   @py_format8s           r   'test_bb4_no_client_returns_empty_resultr      s   T2I13Z\BFf011111111:111:111111f111f111111011101111111111==B=B=B66=B$"$"$$$$"$$$$$$6$$$6$$$$$$"$$$$$$$r   c                    t               } | j                  }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      dz  }t        j                  d| j                   d      dz   d	|iz  }t        t        j                  |            d
x}x}}y
)zGWB1: model_name defaults to 'gemini-pro' (not Flash) when not supplied.z
gemini-prorP   z2%(py2)s
{%(py2)s = %(py0)s.model_name
} == %(py5)srg   r   z'Expected model_name='gemini-pro', got ''z
>assert %(py7)sr   N)r   
model_namer_   rd   r]   r^   r`   ra   re   rb   rc   rg   rx   rk   rh   r   r   s         r   $test_wb1_default_model_is_gemini_pror      s     I < </  <                   $0    2)2F2F1GqI     r   c                    dd} t        |       }|j                  t               t                     }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                  }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}}y)uR   WB2: LLM returning invalid JSON → empty DistillationResult, no exception raised.c                     y)NzTHIS IS NOT JSON {{{{{{{r   r!   s    r   _bad_clientzLtest_wb2_json_parse_failure_returns_empty_not_exception.<locals>._bad_client   s    )r   rE   rG   rH   rI   r   rJ   NrP   r   r   r   r   r   r   r$   r   )	r   rg   rI   rh   ri   rx   rk   r   r   s	            r   7test_wb2_json_parse_failure_returns_empty_not_exceptionr      s   * [9I13Z\BFf011111111:111:111111f111f111111011101111111111==B=B=B66=B$"$"$$$$"$$$$$$6$$$6$$$$$$"$$$$$$$r   c                    d} t        dd      g}t        t        ||             }|j                  t	               t                     }|j                  }|| k(  }|st        j                  d|fd|| f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      d	t        j                         v st        j                  |       rt        j                  |       nd	d
z  }t        j                  d|  d|j                   d      dz   d|iz  }t        t        j                  |            dx}}y)zAWB3: week_summary field is extracted correctly from LLM response.zJGenesis executed 12 sessions. Three failures resolved via axiom evolution.r7   g333333?)r   rE   rP   )z4%(py2)s
{%(py2)s = %(py0)s.week_summary
} == %(py4)srI   expected_summaryrt   zExpected week_summary='z', got 'r   z
>assert %(py6)sru   N)r   r   r,   r\   r.   r@   r   r_   rd   r]   r^   r`   ra   re   rb   rc   )r   r*   rg   rI   rx   rh   ri   ry   s           r   test_wb3_week_summary_extractedr      s:   c&q$/0K";=MNI 13Z\BF "22   "2                    #3    #3    ""2!38F<O<O;PPQR    r   c                    d} t         | k(  }|st        j                  d|fdt         | f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |       dz  }t        j                  dt                dz   d|iz  }t        t        j                  |            d	x}} y	)
z6WB4: CONFIDENCE_THRESHOLD constant equals exactly 0.6.333333?rP   z%(py0)s == %(py3)sr   rK   rU   z'Expected CONFIDENCE_THRESHOLD=0.6, got z
>assert %(py5)srV   N)
r   r_   rd   r]   r^   r`   ra   re   rb   rc   )rj   rx   @py_format4r   s       r   $test_wb4_confidence_threshold_is_0_6r      s    #& 3&  3                $'    22F1GH    r   c                 J   t        dd      g} t        t        |             }|j                  t	               t                     }|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                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}|j                  d   }	|	j                   }d}
||
k(  }|st        j                  d|fd||
f      t        j                  |	      t        j                  |      t        j                  |
      dz  }dd|iz  }t        t        j                  |            dx}	x}x}}
y)z9Axiom with confidence exactly 0.6 (boundary) is included.r7   r   rE   rP   rR   rS   rI   rT   r   rY   Nr   )z2%(py3)s
{%(py3)s = %(py1)s.confidence
} == %(py6)s)rL   rU   ru   zassert %(py8)srW   )r   r   r,   r\   r.   r@   r   rS   r_   rd   r]   r^   r`   ra   rb   rc   r   )r*   rg   rI   rj   rk   rl   rm   rn   ro   @py_assert0@py_assert5ry   s               r   0test_boundary_confidence_exactly_0_6_is_includedr      sJ   &q#./K\+-FGI13Z\BF}}"3}""""""""""""3"""3""""""v"""v"""}"""""""""""""==-&&-#-&#----&#------&---#-------r   c                    t        dd      g} t        t        |             }|j                  t	               t                     }|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                  |      t        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}x}x}}y)z>Axiom with confidence 0.59 (just below threshold) is excluded.r7   gzG?rE   r   rP   rR   rS   rI   rT   r   rY   N)r   r   r,   r\   r.   r@   r   rS   r_   rd   r]   r^   r`   ra   rb   rc   )	r*   rg   rI   rj   rk   rl   rm   rn   ro   s	            r   3test_boundary_confidence_just_below_0_6_is_excludedr      s    &q$/0K\+-FGI13Z\BF}}"3}""""""""""""3"""3""""""v"""v"""}"""""""""""""r   c                 B   t        t        g             } | j                  t               t	                     }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                  }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}}y)uL   LLM returns empty axioms list → DistillationResult with empty axioms list.rE   rG   rH   rI   r   rJ   NrP   r   r   r   r   )r   r,   r\   r.   r@   rH   r   r]   r^   r_   r`   ra   rb   rc   r   rd   r   s           r   "test_empty_axioms_list_in_responser      s!   \"-=>I13Z\BFf011111111:111:111111f111f111111011101111111111==B=B=B66=Br   c                 
   ddddddgdg} t        t        |             }|j                  t               t	                     }|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                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}|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}}|	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}}|	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}}|	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}}|	j&                  }
dd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}}y)zNAll Axiom fields (id, content, category, confidence, source_saga_ids) are set.r|   zRead before buildresearchgffffff?r   saga_002r   rE   r7   rP   rR   rS   rI   rT   r   rY   Nr   )z*%(py2)s
{%(py2)s = %(py0)s.id
} == %(py5)sar   r   r   )z/%(py2)s
{%(py2)s = %(py0)s.content
} == %(py5)s)z0%(py2)s
{%(py2)s = %(py0)s.category
} == %(py5)s)z2%(py2)s
{%(py2)s = %(py0)s.confidence
} == %(py5)s)z7%(py2)s
{%(py2)s = %(py0)s.source_saga_ids
} == %(py5)s)r   r,   r\   r.   r@   r   rS   r_   rd   r]   r^   r`   ra   rb   rc   r   r   r   r   r   )r*   rg   rI   rj   rk   rl   rm   rn   ro   r   rx   rh   r   r   s                 r   test_axiom_fields_all_populatedr      s5    )*" *J7	
K \+-FGI13Z\BF}}"3}""""""""""""3"""3""""""v"""v"""}"""""""""""""aA44)))4)))))4)))))))1)))1)))4)))))))))))99+++9+++++9+++++++1+++1+++9+++++++++++::##:####:######1###1###:##########<<4<4<411<48Z 88 88888 888888818881888888 88888888r   c                    ddl } | j                  } |t              }|sddt        j                         v st        j                  |       rt        j                  |       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}}| j                  } |t              }|sddt        j                         v st        j                  |       rt        j                  |       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}}| j                  t              D ch c]  }|j                   }}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}||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}}| j                  t              D ch c]  }|j                   }	}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}||	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}||	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}||	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}||	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}}yc c}w c c}w )zHDistillationResult and Axiom are proper dataclasses with correct fields.r   NzNassert %(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.is_dataclass
}(%(py3)s)
}dataclassesr   r   r   r   )in)z%(py1)s in %(py3)s	dr_fields)rL   rU   assert %(py5)srV   r   r   	ax_fieldsr   r   r   r   )r   is_dataclassr   r]   r^   r_   r`   ra   rb   rc   r   fieldsnamerd   )
r   rx   rk   r   fr   r   rj   r   r   s
             r   %test_distillation_result_is_dataclassr     s   ##7#$677777777;777;777#777777$6777$67777777777##*#E********;***;***#******E***E**********!,!3!34F!GHAHIH 8y    8y   8      y   y       &>Y&&&&>Y&&&>&&&&&&Y&&&Y&&&&&&&!,!3!3E!:;A;I;4949499!9	!!!!9	!!!9!!!!!!	!!!	!!!!!!!":"""":""":""""""""""""""""$<9$$$$<9$$$<$$$$$$9$$$9$$$$$$$)	))))	)))))))))	)))	))))))) I <s   [	:[c                 8   dd} t        |       }|j                  t               t                     }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                  }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}}y)u@   LLM returns a JSON list (not dict) → empty DistillationResult.c                6    t        j                  ddddg      S )N	epoch_001xr~   )r   r   r   r'   r   s    r   _list_clientz?test_non_dict_json_response_returns_empty.<locals>._list_client'  s    zz+#SQRSSr   rE   rG   rH   rI   r   rJ   NrP   r   r   r   r   r$   r   r\   r.   r@   rH   r   r]   r^   r_   r`   ra   rb   rc   r   rd   )	r   rg   rI   rh   ri   rx   rk   r   r   s	            r   )test_non_dict_json_response_returns_emptyr   %  s$   T \:I13Z\BFf011111111:111:111111f111f111111011101111111111==B=B=B66=Br   c                    ddl m} m}m}m} | t        u }|st        j                  d|fd| t        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z  }dd	|iz  }t        t        j                  |            d
}|t        u }|st        j                  d|fd|t        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z  }dd	|iz  }t        t        j                  |            d
}|t        u }|st        j                  d|fd|t        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z  }dd	|i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  }dd|iz  }	t        t        j                  |	            d
x}}y
)z\core.epoch __init__ exports AxiomDistiller, Axiom, DistillationResult, CONFIDENCE_THRESHOLD.r   r   )is)z%(py0)s is %(py2)sADr   )rK   rM   zassert %(py4)srN   NAr   DRr   r   rP   r   CTr   r   rV   )
core.epochr   r   r   r   r_   rd   r]   r^   r`   ra   rb   rc   )
r   r   r   r   rx   @py_format3ri   rj   r   r   s
             r   )test_package_init_exports_axiom_distillerr   1  s     222:111#####2#######2###2##################29222r   c                    t        d      } | j                  }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |       rt        j                  |       ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)
z8model_name passed to constructor is stored as attribute.zgemini-1.5-pro)r   rP   r   rg   r   r   r   N)
r   r   r_   rd   r]   r^   r`   ra   rb   rc   r   s         r   test_custom_model_name_storedr   @  s    *:;I3#33#33333#333333393339333333#33333333r   c                 8   dd} t        |       }|j                  t               t                     }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                  }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}}y)uM   If gemini_client raises an unexpected exception → empty DistillationResult.c                    t        d      )Nznetwork timeout)RuntimeErrorr   s    r   _crashing_clientzHtest_runtime_exception_in_client_returns_empty.<locals>._crashing_clientH  s    ,--r   rE   rG   rH   rI   r   rJ   NrP   r   r   r   r   r$   r   )	r   rg   rI   rh   ri   rx   rk   r   r   s	            r   .test_runtime_exception_in_client_returns_emptyr   F  s$   . -=>I13Z\BFf011111111:111:111111f111f111111011101111111111==B=B=B66=Br   __main__zBB1: 7 axioms returnedu%   BB2: low-confidence filtered (10→7)z)BB3: axiom ID format epoch_YYYY_MM_DD_NNNu   BB4: no client → empty resultz WB1: default model is gemini-prou(   WB2: JSON parse failure → empty resultzWB3: week_summary extractedz WB4: CONFIDENCE_THRESHOLD == 0.6zEDGE: boundary 0.6 includedzEDGE: boundary 0.59 excludedzEDGE: empty axioms listz EDGE: all axiom fields populatedz%EDGE: DistillationResult is dataclassu   EDGE: non-dict JSON → emptyz$PKG: __init__ exports AxiomDistillerzEDGE: custom model_name storedu(   EDGE: client runtime exception → emptyz	  [PASS] r7   z	  [FAIL] z: 
/z tests passedz(ALL TESTS PASSED -- Story 9.05 (Track B))r   r8   r   floatr
   r%   r&   dict)zA good week.)r*   z
list[dict]r   r%   r&   object)7r>   
__future__r   builtinsr]   _pytest.assertion.rewrite	assertionrewriter_   r(   r   syspytestGENESIS_ROOTpathinsertcore.epoch.axiom_distillerr   r   r   r   r   r,   r.   r@   rp   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r;   	tracebacktestspassedrS   totalr   fnprint	Exceptionexc	print_excexitr   r   r   <module>r      sR  ( #    	 
  'sxxHHOOA|$   "		 	
 
 4 4' '
(8".%%.#9.*&	4	  z 
"#AB	02YZ	46NO	*,ST	+-QR	35lm	&(GH	+-QR	&(XY	')\]	"$FG	+-LM	02WX	(*ST	/1Z[	)+HI	35cd#E( FJE "b	"DIdV$%aKF	" 
Bvhawm
,-89M <  	"IdV2cU+,I!!	"s   	EFE<<F