Skip to content

Conflict policies — contradicting diffs

Module: agentdescent.defaults, agentdescent.fusion · Contract: ConflictPolicy.resolve(artifact, cards) -> (survivors, dropped)

Two diffs contradict when they write the same key with different values. Overlap alone is not a conflict — two workers proposing the same rule collapse to one. This step runs before fusion, which is why the choice here decides what fusion ever gets to see.

Implemented

Policy Rule Reach for it when
DefaultConflict drop the contradicting loser, keep whichever scores better (PCGrad-style) the default; single-key artifacts where one value must win
KeepContradictions pass contradictions through untouched, for fusion to resolve only as a pair with ReflectiveFusion — installed alone it changes nothing, installed with it the contradictions are merged instead of dropped
AdvantageConflict break the tie by group-relative advantage instead of raw score group-standardised evidence exists and raw scores are noisy across task clusters

Use reflective_merge(completion) to install the KeepContradictions + ReflectiveFusion pair correctly — see fusion policies.

from agentdescent import Policies, evolve
from agentdescent.advantage import AdvantageConflict

evolve(tasks, reward, agent=agent, policies=Policies(
    conflict=AdvantageConflict(margin=0.5)))    # falls back to DefaultConflict

AdvantageConflict() wraps DefaultConflict when given no inner. That rule scores a tie on the verifier, which is built inside the engine and which a caller cannot supply — so the aggregator hands it over through the policy's optional bind(verifier) hook when the policy is installed, and the wrapper forwards it. Nothing here has to see a verifier. Before this only fusion was bound, and a wrapped default conflict rule could be installed only from inside an aggregator_factory. See acceptance policies for the hooks themselves.