
    i$F                       U d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlZddlZddlmZ ddlmZ ddlmZmZmZmZ ddlZdZeej.                  vrej.                  j1                  de       ddlmZmZ dd	lmZmZ dd
lm Z  ddl!m"Z" 	 	 d%	 	 	 	 	 	 	 	 	 d&dZ#d'd(dZ$d)d(dZ%dddZ&de'd<   dZ(d*d+dZ)d Z*d Z+d Z,d Z-d Z.d Z/d Z0d Z1d Z2d Z3d  Z4d! Z5d" Z6d# Z7d$ Z8y),u  
tests/track_b/test_story_7_02.py

Story B-7.02: SemanticMergeInterceptor — Opus Contradiction Resolver

Black Box Tests (BB1–BB5):
    BB1  Non-conflicting deltas → used_opus=False, merged_patch contains all ops
    BB2  Conflicting deltas + mock Opus → used_opus=True, resolved patch returned
    BB3  Opus returns invalid JSON → fallback to fast_merge of non-conflicting deltas
    BB4  Empty deltas → success=True, empty merged_patch, used_opus=False
    BB5  Single delta → fast path, used_opus=False

White Box Tests (WB1–WB4):
    WB1  ConflictDetector.detect called before any Opus invocation
    WB2  used_opus=False in fast-path resolution
    WB3  MergePromptBuilder.build called with correct args when conflicts exist
    WB4  latency_ms > 0 for all paths
    )annotationsN)datetime)Any)	AsyncMock	MagicMockpatchcallz/mnt/e/genesis-systemSemanticMergeInterceptorMergeResult)ConflictDetectorConflictReport)MergePromptBuilder)
StateDeltac                P    t        | ||t        |      t        dddddd            S )z;Create a StateDelta with the given patch stored as a tuple.i           r   )agent_id
session_idversion_at_readr   submitted_at)r   tupler   )r   r   r   versions       6/mnt/e/genesis-system/tests/track_b/test_story_7_02.py
make_deltar   6   s3     EldAr2q!4     c                    t        j                  | |d      }t               }||_        t               }||j                  _        |`|S )z
    Return a synchronous mock Opus client whose generate_content() method
    returns a response with a ``.text`` attribute containing valid JSON.
    resolved_patchresolution_rationale)jsondumpsr   textgenerate_contentreturn_valuegenerate_content_asyncr    	rationaleresponse_jsonmock_responseclients        r   make_opus_clientr-   F   sN    
 JJ( )  M KM&M[F+8F(%Mr   c                    t        j                  | |d      }t               }||_        t               }t	        |      |_        |S )z
    Return an async mock Opus client whose generate_content_async() coroutine
    returns a response with a ``.text`` attribute containing valid JSON.
    r   )r&   )r"   r#   r   r$   r   r'   r(   s        r   make_async_opus_clientr/   Y   sG    
 JJ( )  M KM&M[F$-=$IF!Mr   active   )statusr   dictSMALL_STATEz/tmp/test_7_02_events.jsonlc                $    t        | t              S )z/Convenience factory using the temp events path.opus_clientevents_path)r   
TMP_EVENTSr7   s    r   make_interceptorr;   p   s    #TTr   c                H    t        j                         j                  |       S )zBRun an async coroutine synchronously (pytest does not auto-await).)asyncioget_event_looprun_until_complete)coros    r   runrA   y   s    !!#66t<<r   c                    t        dddddg      } t        dddddg      }t               }t        |	      }t        |j	                  | |gt
        d
            }|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                   d      dz   d|iz  }	t        t        j                  |	            dx}x}}|j"                  D 
ch c]  }
|
d   	 }}
d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}d}||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$                  j'                          yc c}
w )u   
    BB1: Two deltas writing to different paths → no conflict detected.
    Opus must NOT be called; merged_patch must include ops from both deltas.
    agent-Aaddz/foo   oppathvalueagent-Bz/barr   r:   r   Tisz/%(py2)s
{%(py2)s = %(py0)s.success
} is %(py5)sresultpy0py2py5assert %(py7)spy7NFz1%(py2)s
{%(py2)s = %(py0)s.used_opus
} is %(py5)sz3Opus must NOT be called when there are no conflicts
>assert %(py7)srH   inz%(py1)s in %(py3)spathspy1py3assert %(py5)srS   )r   r   r;   rA   merger4   success
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation	used_opus_format_assertmsgmerged_patchr%   assert_not_called)delta_adelta_br7   interceptorrO   @py_assert1@py_assert4@py_assert3@py_format6@py_format8rG   r[   @py_assert0@py_assert2@py_format4s                  r   'test_bb1_non_conflicting_deltas_no_opusry      s5   
 E6A%N$OPGE6A%N$OPG+K"{;K""GW#5{A"NOF>>!T!>T!!!!>T!!!!!!6!!!6!!!>!!!T!!!!!!![u[u$[[[u[[[[[[6[[[6[[[[[[u[[[&[[[[[[[[ #)"5"56BRZ6E66U?6U6UU6U?6U6UU   224 7s   Nc                    t        dddddg      } t        dddddg      }ddddg}t        |d	      }t        |
      }t        |j	                  | |gt
        d            }|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}|j                   }||k(  }|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  }dd|i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'                          y)u   
    BB2: Two deltas conflict on the same path → Opus is invoked.
    The returned resolved_patch and rationale must be propagated.
    rC   replacez/statusr0   rF   rJ   inactivezagent-A winsr    r)   r:   r   rK   TrL   rN   rO   rP   rT   rU   NrV   ==z4%(py2)s
{%(py2)s = %(py0)s.merged_patch
} == %(py4)sresolvedrQ   rR   py4assert %(py6)spy6z<%(py2)s
{%(py2)s = %(py0)s.resolution_rationale
} == %(py5)s)r   r-   r;   rA   r`   r4   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rl   r!   r%   assert_called_oncern   ro   r   r7   rp   rO   rq   rr   rs   rt   ru   @py_format5@py_format7s                r   'test_bb2_conflicting_deltas_opus_calledr      s\   
 IyS[%\$]^GIyS]%^$_`G )hGHH"(nUK"{;K""GW#5{A"NOF>>!T!>T!!!!>T!!!!!!6!!!6!!!>!!!T!!!!!!!#t#t####t######6###6######t#######*(****(******6***6*********(***(*******&&8.8&.8888&.88888868886888&888.8888888  335r   c                    t        dddddg      } t        dddddg      }t        dd	d
ddg      }t               }d|_        t               }||j                  _        |`t        |      }t        |j                  | ||gt        d            }|j                  }d}||u }	|	st        j                  d|	fd||f      dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |      dz  }
dd|
iz  }t#        t        j$                  |            dx}x}	}|j&                  }d}||u }	|	st        j                  d|	fd||f      dt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |      dz  }
dd|
iz  }t#        t        j$                  |            dx}x}	}|j(                  D ch c]  }|d   	 }}d
}||v }|st        j                  d|fd||f      t        j                   |      dt        j                         v st        j                  |      rt        j                   |      nddz  }dd |iz  }
t#        t        j$                  |
            dx}}d}||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 )#u   
    BB3: Opus returns malformed JSON → SemanticMergeInterceptor falls back to
    fast_merge of non-conflicting deltas only (partial merge).
    used_opus must be False (Opus never successfully resolved).
    rC   r{   /xXrF   rJ   Yagent-CrD   z/safe*   z
NOT_JSON {r:   rE   rK   TrL   rN   rO   rP   rT   rU   NFrV   rH   rX   rZ   r[   r\   r_   rS   )not in)z%(py1)s not in %(py3)s)r   r   r$   r%   r&   r'   r;   rA   r`   r4   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rl   )delta_conflict_adelta_conflict_bdelta_cleanbad_responser7   rp   rO   rq   rr   rs   rt   ru   rG   r[   rv   rw   rx   s                    r   #test_bb3_opus_invalid_json_fallbackr      sg    ")YWZ.[-\]!)YWZ.[-\]!)UGVX.Y-Z[K ;L$L+K0<K  -*"{;K""	+[9 #  F >>!T!>T!!!!>T!!!!!!6!!!6!!!>!!!T!!!!!!!$u$u$$$$u$$$$$$6$$$6$$$$$$u$$$$$$$ #)"5"56BRZ6E67e7e7ee 4u4u4uu	 7s   .Nc                    t               } t        | j                  g t        d            }|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}}|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[   
    BB4: Passing an empty list → success=True, empty merged_patch, used_opus=False.
    r   rK   TrL   rN   rO   rP   rT   rU   NFrV   r~   )z4%(py2)s
{%(py2)s = %(py0)s.merged_patch
} == %(py5)s)r;   rA   r`   r4   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rl   )rp   rO   rq   rr   rs   rt   ru   s          r   test_bb4_empty_deltasr      sy    #$K""2{A">?F>>!T!>T!!!!>T!!!!!!6!!!6!!!>!!!T!!!!!!!$u$u$$$$u$$$$$$6$$$6$$$$$$u$$$$$$$$"$"$$$$"$$$$$$6$$$6$$$$$$"$$$$$$$r   c                 &   t        dddddg      } t               }t        |j                  | gt        d            }|j
                  }d}||u }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|j                  }d}||u }|st        j                  d	|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}|j                  D ch c]  }|d   	 }	}d}
|
|	v }|st        j                  d|fd|
|	f      t        j                  |
      dt        j                         v st        j                  |	      rt        j                  |	      nddz  }dd|iz  }t        t        j                  |            dx}
}yc c}w )u\   
    BB5: A single delta can never conflict with itself → fast path, used_opus=False.
    zagent-XrD   z/soloonlyrF   rE   rK   TrL   rN   rO   rP   rT   rU   NFrV   rH   rX   rZ   r[   r\   r_   rS   r   r;   rA   r`   r4   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rl   )deltarp   rO   rq   rr   rs   rt   ru   rG   r[   rv   rw   rx   s                r   test_bb5_single_delta_fast_pathr      s    y%6#R"STE"$K""E7K"CDF>>!T!>T!!!!>T!!!!!!6!!!6!!!>!!!T!!!!!!!$u$u$$$$u$$$$$$6$$$6$$$$$$u$$$$$$$"("5"56BRZ6E67e7e7ee 7s   Jc                    t        dddddg      } t        dddddg      }ddddg}t        |      }t        |	      }g |j                  j                  fd
}|j
                  fd}||j                  _        ||_        t        |j                  | |gt        d             d   }d}||k(  }	|	st        j                  d|	fd||f      t        j                  |      t        j                  |      dz  }
t        j                  d      dz   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  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}}	y)z
    WB1: ConflictDetector.detect() must be called as the FIRST step, even when
    conflicts exist and Opus is eventually invoked.
    rC   r{   z/krE   rF   rJ   r   r    r:   c                6    j                  d        |       S )Ndetectappend)deltas
call_orderoriginal_detects    r   patched_detectzLtest_wb1_conflict_detector_detect_called_before_opus.<locals>.patched_detect  s    (#v&&r   c                6    j                  d        |       S )Nopusr   )promptr   original_generates    r   patched_generatezNtest_wb1_conflict_detector_detect_called_before_opus.<locals>.patched_generate
  s    &! ((r   rK   r   r   r~   z%(py1)s == %(py4)sr]   r   z#detect() must be called before Opusz
>assert %(py6)sr   Nr   rX   rZ   r   r\   z$Opus must be called on conflict pathz
>assert %(py5)srS   )r   r-   r;   detectorr   r%   rA   r`   r4   rb   rc   rg   rk   rh   ri   rd   re   rf   )rn   ro   r   r7   rp   r   r   rv   rs   rw   r   r   rx   rt   r   r   r   s                 @@@r   4test_wb1_conflict_detector_detect_called_before_opusr      sx   
 Ita%P$QRGIta%P$QRG $;<H"(;K"{;KJ!**11O' $44) #1K#3K 7G,k1EFa=KHK=H$KKK=HKKK=KKKHKKK&KKKKKKKKG6ZGGG6ZGGG6GGGGGGZGGGZGGGG!GGGGGGGr   c                 0   t        dddddg      } t        dddddg      }t               }t        |j                  | |gt        d	            }|j
                  }d
}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)zW
    WB2: On a non-conflicting merge, used_opus is explicitly False in the result.
    rC   rD   /prE   rF   rJ   z/qr   rK   FrL   rV   rO   rP   rT   rU   N)r   r;   rA   r`   r4   rj   rb   rc   rd   re   rf   rg   rh   ri   )	rn   ro   rp   rO   rq   rr   rs   rt   ru   s	            r   %test_wb2_used_opus_false_on_fast_pathr     s     E4!%L$MNGE4!%L$MNG"$K""GW#5{A"NOF$u$u$$$$u$$$$$$6$$$6$$$$$$u$$$$$$$r   c                    t        dddddg      } t        dddddg      }ddddg}t        |      }t        |	      }i |j                  j                  fd
}||j                  _        ddd}t        |j                  | |g|d             d   }| |g}||k(  }	|	slt        j                  d|	fd||f      t        j                  |      t        j                  |      dz  }
dd|
iz  }t        t        j                  |            dx}x}	}d   }t        |t              }|sddt        j                         v st        j                   t              rt        j                  t              ndt        j                  |      dt        j                         v st        j                   t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            dx}}d   }|j"                  }	d}|	|u }|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}}d!   }||k(  }	|	st        j                  d|	fd"||f      t        j                  |      d#t        j                         v st        j                   |      rt        j                  |      nd#d$z  }d%d&|iz  }t        t        j                  |            dx}}	d'   }d}||k(  }	|	slt        j                  d|	fd||f      t        j                  |      t        j                  |      dz  }
dd|
iz  }t        t        j                  |            dx}x}	}y)(z
    WB3: When conflicts exist, MergePromptBuilder.build() must receive:
    - the full delta list
    - the ConflictReport produced by detect()
    - current_state
    - version
    rC   r{   z/mv1rF   rJ   v2r   r:   c                B    | d<   |d<   |d<   |d<    | |||      S )Nr   reportstater    )r   r   r   r   capturedoriginal_builds       r   patched_buildzMtest_wb3_merge_prompt_builder_called_with_correct_args.<locals>.patched_build6  s<    ##!%ffeW==r   genesis	   )contextverrK   r   r~   r   r   r   r   Nr   z5assert %(py5)s
{%(py5)s = %(py0)s(%(py2)s, %(py3)s)
}
isinstancer   )rQ   rR   r^   rS   TrL   )z5%(py3)s
{%(py3)s = %(py1)s.has_conflicts
} is %(py6)s)r]   r^   r   assert %(py8)spy8r   )z%(py1)s == %(py3)scurrent_stater\   r_   rS   r   )r   r-   r;   prompt_builderbuildrA   r`   rb   rc   rg   rh   ri   r   r   rd   re   rf   has_conflicts)rn   ro   r   r7   rp   r   r   rv   rs   rw   r   r   rq   rr   rt   @py_assert5@py_format9rx   r   r   s                     @@r   6test_wb3_merge_prompt_builder_called_with_correct_argsr   $  s    Itd%S$TUGItd%S$TUG $>?H"(;K"{;KH //55N> (5K$ )!4M7G,mQGHH3'7!33!33333!3333333!33333333x(9:(.99999999:999:999(999999.999.9999999999H3++3t3+t3333+t333333+333t3333333G------------------------I#!#!####!######!#######r   c                    t        dddddg      } t        dddddg      }t               }t        |j                  | |gt        d	            }|j
                  }d
}||kD  }|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}}t        dddddg      }	t        dddddg      }
ddddg}t        |      }t        |      }t        |j                  |	|
gt        d	            }|j
                  }d
}||kD  }|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}}t!               }d|_        t!               }||j$                  _        |`t        |      }t        dddd dg      }t        d!ddd"dg      }t        |j                  ||gt        d	            }|j
                  }d
}||kD  }|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)%zT
    WB4: latency_ms must be > 0 for all code paths (fast, opus, and fallback).
    rC   rD   z/arE   rF   rJ   z/br   rK   r   )>)z1%(py2)s
{%(py2)s = %(py0)s.latency_ms
} > %(py5)sresult_fastrP   z%Fast path latency_ms must be positiverW   rU   Nr   r{   r   Azagent-DBr   r:   result_opusz%Opus path latency_ms must be positiveINVALIDzagent-Ez/yEzagent-FFresult_fallbackz)Fallback path latency_ms must be positive)r   r;   rA   r`   r4   
latency_msrb   rc   rd   re   rf   rg   rk   rh   ri   r-   r   r$   r%   r&   r'   )rn   ro   rp   r   rq   rr   rs   rt   ru   delta_cdelta_dr   r7   interceptor_opusr   r   
bad_clientinterceptor_fallbackdelta_edelta_fr   s                        r   &test_wb4_latency_ms_positive_all_pathsr   I  s   
 E4!%L$MNGE4!%L$MNG"$Kk'''(:KQR'STK!!NAN!A%NNN!ANNNNNN;NNN;NNN!NNNANNN'NNNNNNNN Itc%R$STGItc%R$STG $=>H"(;K'K@&,,gw-?VW,XYK!!NAN!A%NNN!ANNNNNN;NNN;NNN!NNNANNN'NNNNNNNN ;L!LJ/;J,)+
CItc%R$STGItc%R$STG.44gw5G^_4`aO%%VV%)VVV%VVVVVV?VVV?VVV%VVVVVV+VVVVVVVVr   c                    t        dddddg      } t        dddddg      }ddddg}t        |d	      }t        |
      }t        |j	                  | |gt
        d            }|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}|j                   }||k(  }|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  }dd|i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'                          y)zE
    Extra: async generate_content_async interface is supported.
    rC   r{   z/zonerF   rJ   twoz
async winsr}   r:   rE   rK   TrL   rN   rO   rP   rT   rU   NrV   r~   r   r   r   r   r   r   )r   r/   r;   rA   r`   r4   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rl   r!   r'   r   r   s                r    test_async_opus_client_interfacer   o  sZ    Ite%T$UVGIte%T$UVG $?@H(LYK"{;K""GW#5{A"NOF>>!T!>T!!!!>T!!!!!!6!!!6!!!>!!!T!!!!!!!#t#t####t######6###6######t#######*(****(******6***6*********(***(*******&&6,6&,6666&,66666666666666&666,6666666&&99;r   c                 R   t        j                  ddidd      } t               }| |_        t               }||j                  _        |`t        dddddg      }t        d	ddd
dg      }t        |      }t        |j                  ||gt        d            }|j                  }d}||u }	|	st        j                  d|	fd||f      dt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      dz  }
dd|
iz  }t'        t        j(                  |            dx}x}	}|j*                  }d}||u }	|	st        j                  d|	fd||f      dt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      dz  }
dd|
iz  }t'        t        j(                  |            dx}x}	}y)uZ   
    Extra: If Opus returns valid JSON but resolved_patch is not a list → fallback.
    rG   r{   oopsr   rC   z/nrE   rF   rJ   r   r:   rK   TrL   rN   rO   rP   rT   rU   NFrV   )r"   r#   r   r$   r%   r&   r'   r   r;   rA   r`   r4   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   )bad_jsonr   r7   rn   ro   rp   rO   rq   rr   rs   rt   ru   s               r   3test_opus_resolved_patch_non_list_triggers_fallbackr     s    zz+ & H ;L L+K0<K  -*Ita%P$QRGIta%P$QRG"{;K""GW#5{A"NOF >>!T!>T!!!!>T!!!!!!6!!!6!!!>!!!T!!!!!!!$u$u$$$$u$$$$$$6$$$6$$$$$$u$$$$$$$r   c                 r   t        dddddg      } t        dddddg      }t        dd	d
ddg      }t        d      }t        |j                  | ||gt        d            }|j
                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}|j                  }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}|j                  D 
ch c]  }
|
d   	 }}
d
}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}yc c}
w ) u`   
    Extra: If no opus_client is provided but conflicts exist → partial merge (no crash).
    rC   r{   r   r   rF   rJ   r   r   rD   z/cleanc   Nr:   rE   rK   TrL   rN   rO   rP   rT   rU   FrV   rH   rX   rZ   r[   r\   r_   rS   r   )rn   ro   r   rp   rO   rq   rr   rs   rt   ru   rG   r[   rv   rw   rx   s                  r   4test_no_opus_client_with_conflicts_triggers_fallbackr     s    Itc%R$STGItc%R$STGE8b%Q$RSG"t4K""GWg#>UV"WXF>>!T!>T!!!!>T!!!!!!6!!!6!!!>!!!T!!!!!!!$u$u$$$$u$$$$$$6$$$6$$$$$$u$$$$$$$"("5"56BRZ6E68u8u8uu 7s    J4c                 4	   ddl } | j                  ddd      5 }|j                  }ddd       	 t        d      }t	        dd	d
ddg      }t        |j                  |gt        d             t        |dd      5 }|D cg c]#  }|j                         s|j                         % }}ddd       t              }d}	||	k\  }
|
st        j                  d|
fd||	f      dt        j                         v st        j                  t              rt        j                   t              nddt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      t        j                   |	      dz  }dd|iz  }t#        t        j$                  |            dx}x}
}	t'        j(                  |d         }|d   }d}||k(  }|slt        j                  d|fd||f      t        j                   |      t        j                   |      dz  }dd|iz  }t#        t        j$                  |            dx}x}}d}||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}}t+        j,                  |       y# 1 sw Y   =xY wc c}w # 1 sw Y   xY w# t+        j,                         w xY w)'zJ
    Extra: Events are written to the events_path on each merge call.
    r   Nwz.jsonlF)modesuffixdeleter6   rC   rD   z/evrE   rF   rK   rzutf-8)encoding)>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)slenlines)rQ   r]   r^   r   r   r   eventsemantic_merger~   r   r   r   r   r   rX   rZ   r\   r_   rS   rj   conflict_count)tempfileNamedTemporaryFilenamer   r   rA   r`   r4   openstripr   rb   rc   rd   re   rf   rg   rh   ri   r"   loadsosunlink)r   tmptmp_pathrp   rn   fhliner   rw   r   rr   r   r   r   rv   rs   r   rx   rt   s                      r   test_events_written_to_jsonlr    s    		$	$% 
% 
 	88
. 
 Yuq)Q(RSKwia@A(C'2 	Bb.0AdDJJLTZZ\AEA	B 5zQzQzQss55zQ

58$W~1!11~!11111~!1111~111!11111111$|u$$$$|u$$$|$$$$$$u$$$u$$$$$$$#{e####{e###{######e###e#######(5((((5(((((((((5(((5(((((((
		(/  B	B 	B 			(sH   Q!AR  =Q3Q.Q.*Q3,NR  !Q+.Q33Q=8R   R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
)zU
    PKG: SemanticMergeInterceptor and MergeResult are exported from core.merge.
    r   r
   rL   )z%(py0)s is %(py2)sSMIr   )rQ   rR   zassert %(py4)sr   NMRr   )
core.merger   r   rb   rc   rd   re   rf   rg   rh   ri   )r  r  rq   @py_format3r   s        r   test_package_exportsr
    s     N*****3*******3***3******************222r   )zsess-001rE   )
r   strr   z
list[dict]r   r  r   intreturnr   )ztest rationale)r    listr)   r  r  r   )zasync rationale)N)r  r   )9__doc__
__future__r   builtinsrd   _pytest.assertion.rewrite	assertionrewriterb   r=   r"   sysr   r   typingr   unittest.mockr   r   r   r	   pytestGENESIS_ROOTrH   insert%core.merge.semantic_merge_interceptorr   r   core.merge.conflict_detectorr   r   core.merge.merge_prompt_builderr   core.coherence.state_deltar   r   r-   r/   r4   __annotations__r9   r;   rA   ry   r   r   r   r   r   r   r   r   r   r   r   r  r
  r   r   r   <module>r      s  & #     
 	   ; ;  'sxxHHOOA|$ X I > 1 !	  	
  &"  (A6T 6 +
U=526* F	%( HF
%"$JWL<(%2$@r   