Smells
Smells
Section titled “Smells”smells is the v2 architectural smell metric. It detects structural anti-patterns, adds optional temporal/co-change/SAT overlays, and emits a composite risk score.
What It Measures
Section titled “What It Measures”- Cycles (with severity buckets)
- Hub-like modules
- God components
- Hierarchy smells (cyclic/deep/wide)
- Dense structure
- Ambiguous interfaces
- Feature concentration and scattered functionality
- Compound overlap risk across smell families
Output Keys (v2)
Section titled “Output Keys (v2)”Core structural keys
Section titled “Core structural keys”| Key | Meaning |
|---|---|
smells.cycles.count | Number of cyclic SCC components |
smells.cycles.mild_count | Mild cycle count |
smells.cycles.moderate_count | Moderate cycle count |
smells.cycles.severe_count | Severe cycle count |
smells.cycles.max_size | Largest cycle size |
smells.hubs.count | Hub-like module count |
smells.god_components.count | God component count |
smells.hierarchy.cyclic_count | Cyclic hierarchy smell count |
smells.hierarchy.deep_count | Deep hierarchy smell count |
smells.hierarchy.wide_count | Wide hierarchy smell count |
smells.structure.dense_count | Dense-structure smell count |
smells.interface.ambiguous_count | Ambiguous-interface smell count |
smells.feature.concentration_count | Feature concentration smell count |
smells.feature.scattered_count | Scattered functionality smell count |
smells.compound.high_risk_module_count | Modules with multi-family high compound risk |
smells.compound.overlap_index | Overlap index across smell families |
smells.total.count | Total smell count across families |
Channel keys
Section titled “Channel keys”| Key | Meaning |
|---|---|
smells.temporal.available | 1 when temporal channel is available |
smells.temporal.new_count | New smell fingerprints vs baseline |
smells.temporal.resolved_count | Resolved smell fingerprints vs baseline |
smells.temporal.persistent_count | Persistent smell fingerprints vs baseline |
smells.temporal.delta | new_count - resolved_count |
smells.cochange.available | 1 when co-change channel is available |
smells.cochange.overlap_ratio | Ratio of smelly modules that are high co-change coupled |
smells.cochange.high_coupled_smelly_module_count | Count of high-coupled smelly modules |
smells.sat_overlap.available | 1 when SAT overlap channel is available |
smells.sat_overlap.overlap_module_count | Smelly modules overlapping SAT-source findings |
smells.sat_overlap.overlap_ratio | Overlap ratio for smelly modules |
Risk keys
Section titled “Risk keys”| Key | Meaning |
|---|---|
smells.risk.structural | Structural risk contribution |
smells.risk.temporal | Temporal contribution |
smells.risk.cochange | Co-change contribution |
smells.risk.sat_overlap | SAT overlap contribution |
smells.risk.overall | Overall smells risk score (0..1) |
smells.risk.confidence | Confidence in overall score (0..1) |
Channel Prerequisites
Section titled “Channel Prerequisites”| Channel | Requires | auto behavior | force behavior |
|---|---|---|---|
| Temporal | Baseline report file (temporal.baseline_report_path) | If missing/unreadable: unavailable (available=0) | Metric run fails |
| Co-change | Git history signals | If unavailable: unavailable (available=0) | Metric run fails if git history cannot be loaded |
| SAT overlap | Findings from shape_validation or effect_violations | If no SAT source findings: unavailable (available=0) | Metric run fails |
off disables a channel entirely and emits available=0.
Findings
Section titled “Findings”smells emits deterministic findings with stable rule IDs (for example: arxo/smells/cycles/component, arxo/smells/hubs/hub-like, arxo/smells/god-components/bottleneck).
Configuration
Section titled “Configuration”metrics: - id: smells enabled: true config: top_k: 10 emit_findings: true channels: temporal_mode: auto # off | auto | force cochange_mode: auto # off | auto | force sat_mode: auto # off | auto | force temporal: baseline_report_path: ".arxo/baselines/smells_prev_report.json" thresholds: cycles: severe_size: 6 moderate_min: 3 moderate_max: 5 hubs: min_degree: 8 percentile: 0.90 adaptive: true god_components: min_degree: 10 betweenness: 0.10 adaptive_betweenness: true hierarchy: deep_depth: 6 wide_fanout: 8 structure: dense_density: 0.12 interface: ambiguous_min_exports: 20 ambiguous_min_fanout: 8 feature: concentration_top_percent: 0.10 concentration_share_threshold: 0.35 scattered_entropy_threshold: 1.50 scattered_partner_groups_min: 3 risk_weights: structural: 0.45 temporal: 0.20 cochange: 0.20 sat_overlap: 0.15Policy Examples
Section titled “Policy Examples”policy: invariants: - metric: smells.cycles.severe_count op: "==" value: 0 - metric: smells.hubs.count op: "<=" value: 3 - metric: smells.risk.overall op: "<=" value: 0.35Migration from Legacy Keys
Section titled “Migration from Legacy Keys”The following legacy keys were removed in v2:
smells.cyclic_dependency_count->smells.cycles.countsmells.cyclic_dependency_severe->smells.cycles.severe_countsmells.cyclic_dependency_moderate->smells.cycles.moderate_countsmells.cyclic_dependency_mild->smells.cycles.mild_countsmells.hub_like_count->smells.hubs.countsmells.god_component_count->smells.god_components.countsmells.total_smell_count->smells.total.countsmells.unstable_dependencies_note->smells.risk.overall