
    D#iAU                       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mZ ddl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mZmZmZ ddlmZ dd	lmZmZ 	 	 	 	 d 	 	 	 	 	 	 	 	 	 d!d
Z 	 	 	 d"	 	 	 	 	 	 	 d#dZ!d$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 Z0d Z1d Z2d Z3d Z4d Z5y)&u!  
tests/track_b/test_story_8_06.py

Story 8.06: CodeProposer — Structural Fix Generator

Black Box Tests (BB1–BB4):
    BB1  Generated interceptor code contains "BaseInterceptor" (string inspection)
    BB2  Proposal fails axiomatic test → validate_proposal returns False
    BB3  Proposal written to data/evolution/proposals/ directory (tmp_path)
    BB4  Valid opus response → CodeProposal with all 5 fields populated

White Box Tests (WB1–WB4):
    WB1  Opus prompt contains existing interceptor code as reference
    WB2  test_file_path follows naming convention "tests/..."
    WB3  Invalid JSON from opus → ValueError raised
    WB4  validate_proposal calls axiomatic_tests.run_all (mock verified)

ALL tests use mocks for opus_client and axiomatic_tests.
ALL file I/O uses tmp_path.
    )annotationsN)Path)	MagicMockcallpatchz/mnt/e/genesis-system)CodeProposerCodeProposalPROPOSE_PROMPT_DEFAULT_PROPOSALS_DIR
Bottleneck)AxiomaticTestsAxiomResultc                8    t        | ||xs ddg|xs ddg      S )z/Return a populated Bottleneck for use in tests.zsaga-001zsaga-002zscar-a1zscar-a2)description	frequencyaffected_saga_idsscar_idsr   )r   r   saga_idsr   s       6/mnt/e/genesis-system/tests/track_b/test_story_8_06.py_make_bottleneckr   :   s1     ">z:&>3i3	     c                H    |rdnd}| ||di d}t        j                  |      S )zGReturn a valid JSON string that CodeProposer._parse_response() accepts.a  from core.interceptors.base_interceptor import BaseInterceptor

class PoolGuardInterceptor(BaseInterceptor):
    async def pre_execute(self, task_payload):
        return task_payload
    async def post_execute(self, result, task_payload):
        pass
    async def on_error(self, error, task_payload):
        return {}
    async def on_correction(self, correction_payload):
        return correction_payload
zclass BadInterceptor:
    pass
def test_placeholder(): pass
	file_pathcode_contenttest_file_pathtest_contentconfig_changes)jsondumps)r   base_interceptorr   r   datas        r   _make_valid_opus_responser%   I   s?    " 
		.	   $(8D ::dr   c                |    |t        |      }nt        t                     }t        ||t        | dz              S )zDReturn a CodeProposer with mocked opus_client and tmp proposals_dir.return_value	proposalsopus_clientaxiomatic_testsproposals_dir)r   r%   r   str)tmp_pathopus_responser,   r+   s       r   _make_proposerr1   h   s@     ];-F-HI'([01 r   c                   t        d      }t        | |      }t               }|j                  |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}|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  }
t        j                  d|j                         dz   d|
iz  }t        t        j                  |            dx}x}	}y)u]   BB1: Generated interceptor code contains "BaseInterceptor" — verified by string inspection.T)r#   r0   z# existing interceptor codeexisting_code_contextz$propose() must return a CodeProposalz7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstanceproposalr	   )py0py1py2py4NBaseInterceptorinz4%(py1)s in %(py5)s
{%(py5)s = %(py3)s.code_content
}r9   py3py5z1Expected 'BaseInterceptor' in code_content, got:

>assert %(py7)spy7)r%   r1   r   proposer6   r	   
@pytest_ar_format_assertmsg@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationr   _call_reprcompare)r/   r0   proposer
bottleneckr7   @py_assert3@py_format5@py_assert0@py_assert4@py_assert2@py_format6@py_format8s               r   1test_bb1_generated_code_contains_base_interceptorrX   {   s   -tDMhmDH!#J
B_`Hh-U-UU/UUUUUUU:UUU:UUUUUUhUUUhUUUUUUUUUUUU-UUUUUU  5 5  55   5          !)    !)    !6    =X=R=R<ST     r   c                h   d}t        j                  d|ddi d      }t        t        |      t	               t        | dz              }t               }|j                  |d	
      }|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}}y)uG   BB2: Proposal fails axiomatic test → validate_proposal returns False.zimport sqlite3
from core.interceptors.base_interceptor import BaseInterceptor

class SqliteInterceptor(BaseInterceptor):
    pass
core/interceptors/bad.pytests/interceptors/test_bad.pydef test_nothing(): pass
r   r'   r)   r*    r4   Fisz%(py0)s is %(py3)sresultr8   rA   zQvalidate_proposal should return False when code contains SQLite (AXIOM_NO_SQLITE)
>assert %(py5)srB   N)r!   r"   r   r   r   r.   r   rE   validate_proposalrF   rN   rH   rI   rJ   rK   rG   rL   rM   )r/   bad_codebad_responserO   rP   r7   ra   rU   @py_assert1@py_format4rV   s              r   4test_bb2_proposal_fails_axiomatic_test_returns_falseri      s   	  ::/ :4 L <8&(([01H
 "#J
"EH''1F 6U?  6U                  	\    r   c           	        t               }t        | |      }t               }|j                  |d      }|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}
||
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"                  }||j$                  z  }|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(                  }||k(  }|st        j                   d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      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}x}x}}||j*                  z  }|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,                  }||k(  }|st        j                   d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      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}x}x}}t/        j0                  |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"   }|j$                  }
||
k(  }|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*                  }
||
k(  }|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'}||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
).zLBB3: Proposal written to proposals_dir/{epoch_id}/ directory using tmp_path.r3   z
# ref coder4   epoch_test_001epoch_idzproposal.json not found at zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}manifestr8   r:   r;   Nzproposal.json==z,%(py2)s
{%(py2)s = %(py0)s.name
} == %(py5)sr8   r:   rB   assert %(py7)srD   zInterceptor file not found: interceptor_filezutf-8)encoding)z|%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.read_text
}(encoding=%(py4)s)
} == %(py10)s
{%(py10)s = %(py8)s.code_content
}r7   )r8   r:   r;   py6py8py10assert %(py12)spy12zTest file not found: 	test_file)z|%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.read_text
}(encoding=%(py4)s)
} == %(py10)s
{%(py10)s = %(py8)s.test_content
}rm   )z%(py1)s == %(py4)s)r9   r;   zassert %(py6)srw   r   )z1%(py1)s == %(py5)s
{%(py5)s = %(py3)s.file_path
}r@   r   )z6%(py1)s == %(py5)s
{%(py5)s = %(py3)s.test_file_path
}r    r=   z%(py1)s in %(py3)smetar9   rA   assert %(py5)srB   )r%   r1   r   rE   write_proposalr   existsrF   rG   rH   rI   rJ   rK   rL   rM   namerN   parentr   	read_textr   r   r   r!   loads)r/   r0   rO   rP   r7   manifest_pathrn   rg   rQ   rR   rT   rV   rW   	epoch_dirru   @py_assert5@py_assert9@py_assert7@py_format11@py_format13r|   r~   rS   rU   @py_format7rh   s                             r   0test_bb3_proposal_written_to_proposals_directoryr      s   -/MhmDH!#J
,OH++H?O+PM M"H??K?KKK ;M?KKKKKKK8KKK8KKK?KKKKKKKKK==+O+=O++++=O++++++8+++8+++=+++O+++++++ I 8#5#55""W"$W$WW(DEUDV&WWWWWWWWWWWWW"WWW$WWWWWW%%PwP%w7P8;P;PP7;PPPPP7;PPPPPPPPPPPPP%PPPwPPP7PPPPPP8PPP8PPP;PPPPPPPP H333IBBBB!6ykBBBBBBB9BBB9BBBBBBBBBBBBII0IH4I4II04IIIII04IIIIIII9III9IIIIIIIII0IIIIIIHIIIHIII4IIIIIIII ::h(('(:;D
///////////////////////2 2 22 22222 2222222222222222 22222222 !<X%<%<<!%<<<<<!%<<<<!<<<<<<X<<<X<<<%<<<<<<<<#t####t#########t###t#######r   c                   t        dd      }t        | |      }t               }|j                  |d      }t        j
                  } ||      }|st        j                  d      dz   d	t        j                         v st        j                  t              rt        j                  t              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}}g }|j                  }t        |t               }|}	|r|j                  }
|
}	|	sd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t        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dz  }|j#                  |       |rldd
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  
      dz  }|j#                  |       t        j$                  |d      i z  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}	x}x}x}}
g }|j&                  }t        |t               }|}	|r|j&                  }
|
}	|	sd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t        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dz  }|j#                  |       |rldd
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |
      dz  }|j#                  |       t        j$                  |d      i z  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}	x}x}x}}
g }|j(                  }t        |t               }|}	|r|j(                  }
|
}	|	sd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t        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dz  }|j#                  |       |rldd
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |
      dz  }|j#                  |       t        j$                  |d      i z  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}	x}x}x}}
g }|j*                  }t        |t               }|}	|r|j*                  }
|
}	|	sd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t        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dz  }|j#                  |       |rldd
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |
      dz  }|j#                  |       t        j$                  |d      i z  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}	x}x}x}}
|j,                  }t        |t.              }|s5t        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
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                  }d}||k(  }|st        j0                  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        j0                  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)*uF   BB4: Valid opus response → CodeProposal with all 5 fields populated.z&core/interceptors/retry_interceptor.pyz,tests/interceptors/test_retry_interceptor.py)r   r   r3   r]   r4   z CodeProposal must be a dataclasszP
>assert %(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.is_dataclass
}(%(py3)s)
}dataclassesr7   r8   r:   rA   rB   NzM%(py8)s
{%(py8)s = %(py2)s(%(py5)s
{%(py5)s = %(py3)s.file_path
}, %(py6)s)
}r6   r.   )r:   rA   rB   rw   rx   z)%(py12)s
{%(py12)s = %(py10)s.file_path
})ry   r{   r   zfile_path must be non-emptyz
>assert %(py15)spy15zP%(py8)s
{%(py8)s = %(py2)s(%(py5)s
{%(py5)s = %(py3)s.code_content
}, %(py6)s)
}z,%(py12)s
{%(py12)s = %(py10)s.code_content
}zcode_content must be non-emptyzR%(py8)s
{%(py8)s = %(py2)s(%(py5)s
{%(py5)s = %(py3)s.test_file_path
}, %(py6)s)
}z.%(py12)s
{%(py12)s = %(py10)s.test_file_path
}z test_file_path must be non-emptyzP%(py8)s
{%(py8)s = %(py2)s(%(py5)s
{%(py5)s = %(py3)s.test_content
}, %(py6)s)
}z,%(py12)s
{%(py12)s = %(py10)s.test_content
}ztest_content must be non-emptyzconfig_changes must be a dictz[
>assert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.config_changes
}, %(py4)s)
}dict)r8   r9   rA   r;   rw   rp   z1%(py2)s
{%(py2)s = %(py0)s.file_path
} == %(py5)srs   rt   rD   )z6%(py2)s
{%(py2)s = %(py0)s.test_file_path
} == %(py5)s)r%   r1   r   rE   r   is_dataclassrF   rG   rH   rI   rJ   rK   rL   rM   r   r6   r.   append_format_boolopr   r   r   r    r   rN   )r/   r0   rO   rP   r7   rg   rT   rV   r   rS   @py_assert11@py_format9r   @py_format14@py_format16rU   r   r   rQ   rW   s                       r   6test_bb4_valid_opus_response_populates_all_five_fieldsr      s   -:EM hmDH!#J
"EH ##Q#H-Q-QQ/QQQQQQQ;QQQ;QQQ#QQQQQQHQQQHQQQ-QQQQQQdh((d:(#.d.d.83E3Ed3Edddddd:ddd:ddddddhdddhddd(dddddd#ddd#ddd.dddd.ddddd8ddd8ddd3EdddddddddGddddddddmh++m:+S1m1m1h6K6Km6Kmmmmmm:mmm:mmmmmmhmmmhmmm+mmmmmmSmmmSmmm1mmmm1mmmmmhmmmhmmm6KmmmmmmmmmMmmmmmmmmsh--s:-s3s3s38O8Os8Ossssss:sss:sssssshssshsss-ssssssssssssss3ssss3sssssssssss8OsssssssssQssssssssmh++m:+S1m1m1h6K6Km6Kmmmmmm:mmm:mmmmmmhmmmhmmm+mmmmmmSmmmSmmm1mmmm1mmmmmhmmmhmmm6KmmmmmmmmmMmmmmmmmm--U:-t4U4UU6UUUUUUU:UUU:UUUUUUhUUUhUUU-UUUUUUtUUUtUUU4UUUUUU I!II!IIIII!IIIIIII8III8IIIIII!IIIIIIII""T&TT"&TTTTT"&TTTTTTT8TTT8TTT"TTT&TTTTTTTTr   c                B	   t               }t        |      }t        |t        | dz              }t	               }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                  |      d
z  }	t        j                  d      dz   d|	iz  }
t        t        j                  |
            dx}x}}|j                   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        dz   d|iz  }t        t        j                  |            d}|j"                  }||v }|st        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z   d|iz  }t        t        j                  |            dx}}|j$                  }t        |      }||v }|sMt        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t        j                         v st        j                  |      rt        j                  |      ndd!z  }
t        j                  d"      d#z   d$|
iz  }t        t        j                  |            dx}x}}y)%zAWB1: Opus prompt contains existing interceptor code as reference.r'   r)   r+   r-   z5class ExistingInterceptor(BaseInterceptor):
    pass
r4      rp   )z2%(py2)s
{%(py2)s = %(py0)s.call_count
} == %(py5)sr+   rs   z'opus_client must be called exactly oncerC   rD   Nr   r=   )z%(py0)s in %(py2)sexisting_codeprompt_usedr8   r:   z=Existing code not found in prompt. Prompt (first 500 chars):
i  z
>assert %(py4)sr;   )z3%(py2)s
{%(py2)s = %(py0)s.description
} in %(py4)srP   ro   z*Bottleneck description missing from prompt
>assert %(py6)srw   )zO%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.frequency
})
} in %(py7)sr.   r8   r9   rA   rB   rD   z(Bottleneck frequency missing from prompt
>assert %(py9)spy9)r%   r   r   r.   r   rE   
call_countrF   rN   rH   rI   rJ   rK   rG   rL   rM   	call_argsr   r   )r/   r0   r+   rO   rP   r   rg   rT   rQ   rV   rW   r   @py_format3rR   r   rU   @py_assert6@py_format10s                     r   5test_wb1_opus_prompt_contains_existing_code_referencer      s   -/M7K([01H "#JMMZ}E !!QQQ!Q&QQQ!QQQQQQQ;QQQ;QQQ!QQQQQQQ(QQQQQQQQ #,,Q/2K K'  =K                (    (    IUYVYIZH[\    
 !!^![0^^^![^^^^^^:^^^:^^^!^^^^^^[^^^[^^^^2^^^^^^^##_3#$_$3___$______3___3______z___z___#___$_____________5________r   c                x   t        d      }t        | |      }t               }|j                  |d      }|j                  }|j
                  }d} ||      }|st        j                  d|j                        dz   d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      t        j                  |      t        j                  |      d
z  }	t        t        j                  |	            dx}x}x}}y)z:WB2: test_file_path follows naming convention 'tests/...'.z)tests/interceptors/test_my_interceptor.py)r   r3   r]   r4   ztests/z.test_file_path must start with 'tests/', got: zr
>assert %(py8)s
{%(py8)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.test_file_path
}.startswith
}(%(py6)s)
}r7   )r8   r:   r;   rw   rx   N)r%   r1   r   rE   r   
startswithrF   rG   rH   rI   rJ   rK   rL   rM   )
r/   r0   rO   rP   r7   rg   rQ   r   r   r   s
             r   0test_wb2_test_file_path_starts_with_tests_prefixr     s-    .BM hmDH!#J
"EH"" "-- h -h7 7   99P9P8ST             #    .    /7    8      r   c                   g d}|D ]v  }t        |      }t        |t        | dz              }t               }t	        j
                  t        t        j                  f      5  |j                  |d       ddd       x y# 1 sw Y   xY w)u2   WB3: Invalid JSON from opus → ValueError raised.)zThis is not JSON at allz!{'single_quotes': 'are not JSON'}z{"incomplete": r]   nullr'   r)   r   r]   r4   N)
r   r   r.   r   pytestraises
ValueErrorr!   JSONDecodeErrorrE   )r/   invalid_responsesrf   r+   rO   rP   s         r   2test_wb3_invalid_json_from_opus_raises_value_errorr     s     * 	C\:#h45
 &'
]]J(<(<=> 	CZrB	C 	C	C	C 	Cs   "BB
	c                   t        j                  dddd      }t        |      }t        |t	        | dz              }t               }t        j                  t        d	      5  |j                  |d
       ddd       y# 1 sw Y   yxY w)uC   WB3 (extended): JSON missing required fields → ValueError raised.core/interceptors/x.pyztests/interceptors/test_x.pypass)r   r   r   r'   r)   r   zmissing required fieldsmatchr]   r4   N)
r!   r"   r   r   r.   r   r   r   r   rE   )r/   incomplete_responser+   rO   rP   s        r   3test_wb3_missing_required_fields_raises_value_errorr   -  s     **-8	&  )<=K([01H "#J	z)B	C ?2>? ? ?s   $BB
c                   t               }t        | |      }t               }t        ddddi       }t	        t
              }t        dg 	      }||j                  _        ||_	        |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"                  |	      t        j"                  |
      dz  }t        j$                  d      dz   d|iz  }t'        t        j(                  |            dx}x}	x}}
|j                  j*                  }|d   r	|d   d   }n|d
   j-                  dd      }|j.                  }	||	k(  }|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t        j"                  |	      dz  }t        j$                  d      dz   d|iz  }t'        t        j(                  |            dx}}	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)#zEWB4: validate_proposal calls axiomatic_tests.run_all (mock verified).r3   zcore/interceptors/guard.pyaw  from core.interceptors.base_interceptor import BaseInterceptor

class GuardInterceptor(BaseInterceptor):
    async def pre_execute(self, task_payload): return task_payload
    async def post_execute(self, result, task_payload): pass
    async def on_error(self, error, task_payload): return {}
    async def on_correction(self, correction_payload): return correction_payload
z tests/interceptors/test_guard.pyr   r   specTpassed
violationsr   rp   )zO%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.run_all
}.call_count
} == %(py7)smock_axiomaticr8   r:   r;   rD   z3axiomatic_tests.run_all must be called exactly oncer   r   Nr   r   r]   )z4%(py0)s == %(py4)s
{%(py4)s = %(py2)s.code_content
}code_argr7   ro   z.run_all must receive the proposal code_contentr   rw   r^   r`   ra   rb   r   rB   )r%   r1   r   r	   r   r   r   run_allr(   r,   rd   r   rF   rN   rH   rI   rJ   rK   rG   rL   rM   r   getr   )r/   r0   rO   rP   r7   r   mock_resultra   rg   rQ   r   r   rW   r   call_kwargsr   rR   r   rU   rh   rV   s                        r   8test_wb4_validate_proposal_calls_axiomatic_tests_run_allr   A  s   -/MhmDH!#J .a :5H  N3NTb9K*5N'-H''1F !! !,,  ,1  ,              "    -    12    	>      !((22K1~q>!$q>%%nb9,, 8,,  8,                          -    	9     6T>6T66Tr   c                    t         j                  }  | 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} }t        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 )z>CodeProposal is a proper dataclass with all 5 required fields.zNassert %(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.is_dataclass
}(%(py3)s)
}r   r	   r   Nr   r=   r}   field_namesr   r   rB   r   r   r   r    )r   r   r	   rH   rI   rF   rJ   rK   rL   rM   fieldsr   rN   )rg   rT   rV   fr   rS   rU   rh   s           r   test_code_proposal_is_dataclassr   u  sl   ##1#L11111111;111;111#111111L111L1111111111#.#5#5l#CDa166DKD%;+%%%%;+%%%;%%%%%%+%%%+%%%%%%%(>[((((>[(((>(((((([((([(((((((*{****{*********{***{*******(>[((((>[(((>(((((([((([(((((((*{****{*********{***{******* Es   Q+c                 :   t        dddd      } t        dddd      }| j                  }i }||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                  }i }||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                  d<   |j                  }i }||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      dz   d|iz  }t        t        j                  |            dx}x}}y)zFconfig_changes defaults to an empty dict (not None, not shared state).za.pyr   ztests/test_a.pyr   r   r   r   zb.pyztests/test_b.pyrp   )z6%(py2)s
{%(py2)s = %(py0)s.config_changes
} == %(py5)sp1rs   rt   rD   Np2valuekeyz3config_changes must not be a shared mutable defaultrC   )r	   r    rF   rN   rH   rI   rJ   rK   rL   rM   rG   )r   r   rg   rT   rQ   rV   rW   s          r   8test_code_proposal_config_changes_defaults_to_empty_dictr     s   	(	
B 
(	
B """"""""""""2"""2"""""""""""""""""""""""""2"""2"""""""""""""&BeYY"YYYYYYYYY2YYY2YYYYYYYYY$YYYYYYYYr   c                    t        dt        | dz              }t               }t        j                  t
        d      5  |j                  |d       ddd       y# 1 sw Y   yxY w)z5propose() without an opus_client raises RuntimeError.Nr)   r   r+   r   r]   r4   )r   r.   r   r   r   RuntimeErrorrE   )r/   rO   rP   s      r   5test_propose_without_opus_client_raises_runtime_errorr     s\    ([01H "#J	|=	9 ?2>? ? ?s   AA%c                V   t        t              }t        dg       |j                  _        t        t               |t        | dz              }t        dddd	
      }|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}}y)zJvalidate_proposal returns False when code_content lacks 'BaseInterceptor'.r   Tr   r)   r*   rZ   zclass SomeClass:
    pass
r[   r\   r   Fr^   r`   ra   rb   z4Should fail when BaseInterceptor not in code_contentrc   rB   Nr   r   r   r   r(   r   r.   r	   rd   rF   rN   rH   rI   rJ   rK   rG   rL   rM   	r/   r   rO   r7   ra   rU   rg   rh   rV   s	            r   9test_validate_proposal_fails_when_base_interceptor_absentr     s     N3N*5Tb*QN'K&([01H
 ,371	H ''1FR6U?RRR6URRRRRR6RRR6RRRURRRRRRRRRRr   c                V   t        t              }t        dg       |j                  _        t        t               |t        | dz              }t        dddd	
      }|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}}y)zPvalidate_proposal returns False when test_file_path doesn't start with 'tests/'.r   Tr   r)   r*   r   z_from core.interceptors.base_interceptor import BaseInterceptor

class X(BaseInterceptor): pass
zsrc/test_x.pyr\   r   Fr^   r`   ra   rb   z;Should fail when test_file_path doesn't start with 'tests/'rc   rB   Nr   r   s	            r   :test_validate_proposal_fails_when_test_path_missing_prefixr     s    N3N*5Tb*QN'K&([01H
 */ '1H ''1FY6U?YYY6UYYYYYY6YYY6YYYUYYYYYYYYYYr   c                $   t               }t        | |      }t               }|j                  |d      }|j	                  |d      }t        |      }|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}
}	|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  }dd|iz  }t        t        j                  |            dx}x}
x}}y)zCwrite_proposal creates the epoch directory structure automatically.r3   r]   r4   	epoch_xyzrl   rp   rr   r   rs   rt   rD   Nr)   )zH%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.parent
}.name
} == %(py7)sr   zassert %(py9)sr   )r%   r1   r   rE   r   r   r   r   rF   rN   rH   rI   rJ   rK   rL   rM   )r/   r0   rO   rP   r7   r   rn   r   rg   rT   rQ   rV   rW   r   r   r   s                   r   .test_write_proposal_creates_epoch_subdirectoryr     sT   -/MhmDH!#J
"EH++H{+KM M"HI>>([(>[((((>[((((((9(((9(((>((([(((((((/  /K/ K//// K//////9///9////// ///K///////r   c           	        t               }t        | |      }t               }|j                  |d      }|j	                  |d      }|j	                  |d      }||k7  }|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  }dd|iz  }	t        t        j                  |	            d}t        |      }
|
j                  } |       }|sd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        t        j                  |            dx}
x}}t        |      }
|
j                  } |       }|sd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        t        j                  |            dx}
x}}t        |      }
|
j                  }|j                   }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                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}x}x}}t        |      }
|
j                  }|j                   }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                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}x}x}}y)zPMultiple write_proposal calls with different epoch_ids produce independent dirs.r3   r]   r4   	epoch_001rl   	epoch_002)!=)z%(py0)s != %(py2)spath1path2r   assert %(py4)sr;   Nz_assert %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}.exists
}()
}r   r   rp   )zg%(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}.parent
}.name
} == %(py10)s)r8   r9   rA   rB   rD   ry   rz   r{   )r%   r1   r   rE   r   rF   rN   rH   rI   rJ   rK   rL   rM   r   r   r   r   )r/   r0   rO   rP   r7   r   r   rg   r   rR   rU   rT   r   rW   r   @py_assert8r   r   s                     r   /test_write_proposal_multiple_epochs_independentr     sc   -/MhmDH!#J
"EH##H{#CE##H{#CEE>5E55EE;;44;;;44;;1;1""1k1"k1111"k11111141114111111111111;111111"111k1111111;1;1""1k1"k1111"k11111141114111111111111;111111"111k11111111r   c                   ddddi d}dt        j                  |       d}t        t        | dz        	      }|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}}y)zD_parse_response correctly handles markdown-fenced JSON from the LLM.zcore/interceptors/fenced.pyz^from core.interceptors.base_interceptor import BaseInterceptor
class X(BaseInterceptor): pass
z!tests/interceptors/test_fenced.pyzdef test_fenced(): pass
r   z```json
z
```r)   )r-   rp   r   r7   rs   rt   rD   Nr<   r=   r?   r@   )r!   r"   r   r.   _parse_responser   rF   rN   rH   rI   rJ   rK   rL   rM   r   )r/   r$   raw_with_fencesrO   r7   rg   rT   rQ   rV   rW   rS   rU   s               r   *test_parse_response_strips_markdown_fencesr     sC    3z=3D "$**T"2!359O#h.D*EFH''8H>!>>!>>>>>!>>>>>>>8>>>8>>>>>>!>>>>>>>>5 5 55 55555 5555555555555555 55555555r   c                   ddl 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
}y
)zAcore.evolution.__init__.py exports CodeProposer and CodeProposal.r   )r   r	   r^   )z%(py0)s is %(py2)sCPr   r   r   r;   N	CProposalr	   )core.evolutionr   r	   rF   rN   rH   rI   rJ   rK   rL   rM   )r/   r   r   rg   r   rR   s         r   test_package_init_exportsr     s    
 222$$$$9$$$$$$9$$$9$$$$$$$$$$$$$$$$r   c                    h d} | D ]  }d| d}|t         v }|st        j                  d|fd|t         f      t        j                  |      dt	        j
                         v st        j                  t               rt        j                  t               nddz  }t        j                  d| d      d	z   d
|iz  }t        t        j                  |            dx}} y)z5PROPOSE_PROMPT template has all required format keys.>   r   r   r   r   r   {}r=   r}   r
   r   z'PROPOSE_PROMPT is missing placeholder {rc   rB   N)
r
   rF   rN   rK   rH   rI   rJ   rG   rL   rM   )required_keysr   rS   rU   rh   rV   s         r   ;test_propose_prompt_template_contains_required_placeholdersr     s    YM 
C5| 	
|~- 	
 	
|~ 	
 	
 		  	
 	
	6	
 	
   . 	
 	
 		  . 	
 	
  7se2>	
 	
 	
 	
 	

r   )z2DB connection pooling code module fails under load   NN)
r   r.   r   intr   list[str] | Noner   r   returnr   )z+core/interceptors/pool_guard_interceptor.pyTz1tests/interceptors/test_pool_guard_interceptor.py)r   r.   r#   boolr   r.   r   r.   )NN)r0   z
str | Noner   r   )6__doc__
__future__r   builtinsrH   _pytest.assertion.rewrite	assertionrewriterF   r   r!   syspathlibr   unittest.mockr   r   r   r   GENESIS_ROOTpathinsertcore.evolution.code_proposerr   r	   r
   r   core.evolution.meta_architectr   core.evolution.axiomatic_testsr   r   r   r%   r1   rX   ri   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r   <module>r     sD  * #      
  0 0  'sxxHHOOA|$  5 F L!%!%	  	
   C!M  		>&B$BU:`< C.?(,h+Z*	?S,Z00 2"6$%
r   