from repo_scoping.candidate_graph.generator import ( CandidateAbilityDraft, CandidateCapabilityDraft, CandidateFeatureDraft, ) from repo_scoping.candidate_graph.normalization import normalize_candidate_drafts from repo_scoping.core.models import SourceReference def ref(fact_id, path): return SourceReference( fact_id=fact_id, path=path, kind="documentation", name=path, ) def test_normalizer_merges_duplicate_abilities_and_nested_claims(): candidates = [ CandidateAbilityDraft( name="LLM Provider Integration", description="Connects to model providers.", confidence=0.55, source_refs=[ref(1, "README.md")], capabilities=[ CandidateCapabilityDraft( name="Use OpenRouter Models", description="Calls OpenRouter.", inputs=["prompt"], outputs=["response"], confidence=0.6, source_refs=[ref(2, "providers.py")], features=[ CandidateFeatureDraft( name="OpenRouter Model Support", type="integration", location="providers.py", confidence=0.6, source_refs=[ref(2, "providers.py")], ) ], ) ], ), CandidateAbilityDraft( name="LLM Provider Integrations", description="Connects prompts to OpenRouter and Claude providers.", confidence=0.7, source_refs=[ref(3, "providers.py")], capabilities=[ CandidateCapabilityDraft( name="OpenRouter Model Support", description="Supports OpenRouter model calls.", inputs=["LLM request"], outputs=["model response"], confidence=0.75, source_refs=[ref(3, "providers.py")], features=[ CandidateFeatureDraft( name="Use OpenRouter Models", type="backend integration", location="src/providers.py", confidence=0.75, source_refs=[ref(3, "providers.py")], ) ], ) ], ), ] normalized = normalize_candidate_drafts(candidates) assert len(normalized) == 1 ability = normalized[0] assert ability.name == "LLM Provider Integrations" assert ability.description == ( "Connects prompts to OpenRouter and Claude providers." ) assert ability.confidence == 0.7 assert {ref.fact_id for ref in ability.source_refs} == {1, 3} assert len(ability.capabilities) == 1 capability = ability.capabilities[0] assert capability.confidence == 0.75 assert capability.inputs == ["prompt", "LLM request"] assert capability.outputs == ["response", "model response"] assert len(capability.features) == 1 assert capability.features[0].confidence == 0.75