""" C3 — Structural coherence. Uses graph analysis to check that the entity relationship graph is well-connected and has meaningful community structure. """ from __future__ import annotations from dataclasses import dataclass, field from typing import Dict, List, Optional from markitect.prompts.dependencies.models import DependencyGraph @dataclass class CoherenceReport: """Results from coherence analysis.""" connected_components: int = 0 largest_component_size: int = 0 modularity: float = 0.0 community_count: int = 0 cohesion: float = 0.0 coupling: float = 0.0 entity_count: int = 0 def to_dict(self) -> dict: return { "concern": "C3", "connected_components": self.connected_components, "largest_component_size": self.largest_component_size, "modularity": round(self.modularity, 4), "community_count": self.community_count, "cohesion": round(self.cohesion, 4), "coupling": round(self.coupling, 4), "entity_count": self.entity_count, } def check_coherence( graph: Optional[DependencyGraph] = None, entity_count: int = 0, ) -> CoherenceReport: """Check structural coherence of the entity relationship graph. Args: graph: The entity relationship graph. If ``None``, returns a report with zero values. entity_count: Total number of entities (for context). Returns: :class:`CoherenceReport` with connectivity and community metrics. """ if graph is None or len(graph.nodes) == 0: return CoherenceReport(entity_count=entity_count) try: from markitect.analysis.graph import ( connected_components, modularity_score, detect_communities, cohesion_coupling, ) except ImportError: return CoherenceReport(entity_count=entity_count) components = connected_components(graph) communities = detect_communities(graph, seed=42) mod = modularity_score(graph, communities=communities) cc = cohesion_coupling(graph, communities=communities) return CoherenceReport( connected_components=len(components), largest_component_size=len(components[0]) if components else 0, modularity=mod, community_count=len(communities), cohesion=cc["cohesion"], coupling=cc["coupling"], entity_count=entity_count or len(graph.nodes), )