
    i                        d Z ddlmZ ddlZddlmZ ddlmZ ddlmZ  ej                  e
      Ze G d d             Z G d	 d
      Zy)u~  
core/merge/swarm_result.py

SwarmResult — data model for a single worker's output in a parallel swarm run.
SwarmConflictDetector — identifies when 2+ workers produce contradictory outputs
for the same session.

Note: This module is Track A of the AIVA RLM Nexus PRD v2.
The name ``SwarmConflictDetector`` is intentionally distinct from
``ConflictDetector`` in core/merge/conflict_detector.py (Track B), which
operates on RFC 6902 StateDelta patches. This class operates on SwarmResult
output dicts instead.

# VERIFICATION_STAMP
# Story: 6.01
# Verified By: parallel-builder
# Verified At: 2026-02-25
# Tests: 29/29
# Coverage: 100%
    )annotationsN)	dataclass)datetime)Anyc                  D    e Zd ZU dZded<   ded<   ded<   ded<   d	ed
<   y)SwarmResultu  
    Represents the output produced by a single swarm worker for a given session.

    Attributes:
        session_id:    Identifier of the conversation/session this result belongs to.
        worker_name:   Name/ID of the worker that produced the result.
        output:        Free-form dict of key→value pairs produced by the worker.
        completed_at:  UTC timestamp when the worker finished.
        confidence:    Confidence score in [0.0, 1.0] for the result.
    str
session_idworker_namedictoutputr   completed_atfloat
confidenceN)__name__
__module____qualname____doc____annotations__     0/mnt/e/genesis-system/core/merge/swarm_result.pyr   r   %   s%    	 OLr   r   c                  B    e Zd ZdZddZddZe	 	 	 	 	 	 	 	 dd       Zy)	SwarmConflictDetectora  
    Identifies when 2+ SwarmResult objects for the same session contain
    contradictory output values.

    Conflict definition
    -------------------
    Two results conflict when they share the same session_id AND have at
    least one common output key whose values are:
        - both non-None, AND
        - not equal to each other.

    Keys present in only one result, or where either value is None, are
    considered complementary and NOT conflicts.
    c                6    t        | j                  |            S )a  
        Return True if 2+ results for the same session have conflicting outputs.

        A conflict requires:
        - Same ``session_id``
        - Same output key
        - Both values non-None
        - Values are not equal

        Args:
            results: List of SwarmResult objects (may span multiple sessions).

        Returns:
            True if at least one conflict exists, False otherwise.
        )boolget_conflicts)selfresultss     r   detectzSwarmConflictDetector.detectR   s      D&&w/00r   c                   t        |      dk  rg S g }i }|D ]-  }|j                  |j                  g       j                  |       / |j	                         D ]g  \  }}t        |      dk  rt        t        |            D ]<  }t        |dz   t        |            D ]  }||   }	||   }
| j                  |	|
|       ! > i t        j                  dt        |      t        |             |S )u"  
        Return all conflicting (result_a, result_b, conflicting_key) tuples.

        For every pair of results sharing the same session_id, each output key
        that appears in both with differing non-None values yields one tuple.
        Each conflicting key generates exactly one tuple per conflicting pair.

        Args:
            results: List of SwarmResult objects to inspect.

        Returns:
            List of (SwarmResult, SwarmResult, str) tuples — one per conflict.
            Empty list when no conflicts exist.
              u@   SwarmConflictDetector.get_conflicts: %d results → %d conflicts)	len
setdefaultr
   appenditemsrange_find_pair_conflictsloggerdebug)r   r   	conflicts
by_sessionrr
   session_resultsijresult_aresult_bs              r   r   z#SwarmConflictDetector.get_conflictsd   s    w<!I!#	 46
 	>A!!!,,3::1=	> ,6+;+;+= 
	M'J?#a' 3/0 Mq1uc/&:; MA.q1H.q1H--h)LMM
	M 	NL	N	

 r   c                    | j                   }|j                   }|j                         |j                         z  }t        |      D ]+  }||   }||   }||||k7  s|j                  | ||f       - y)z
        Append (result_a, result_b, key) to *conflicts* for every key that
        is present in both outputs with differing non-None values.

        Mutates *conflicts* in place.
        N)r   keyssortedr&   )	r2   r3   r,   output_aoutput_bshared_keyskeyval_aval_bs	            r   r)   z*SwarmConflictDetector._find_pair_conflicts   s     $,??#+?? mmo7+& 
	<CSMESME } ~  (Hc!:;
	<r   N)r   list[SwarmResult]returnr   )r   r=   r>   list[tuple])r2   r   r3   r   r,   r?   r>   None)r   r   r   r   r    r   staticmethodr)   r   r   r   r   r   >   sJ    &1$*` <<< < 
	< <r   r   )r   
__future__r   loggingdataclassesr   r   typingr   	getLoggerr   r*   r   r   r   r   r   <module>rG      sR   * #  !  			8	$   0r< r<r   