ovecc diagnose
Named architectural smells at component (directory) granularity: cycles with per-hop
file:line witness edges, hub-like and god components, zone of pain (Martin
distance), dense structure, hotspots, unstable interfaces, change coupling, and
modularity violations. Every finding carries evidence, the design principle it
breaks, a deterministic confidence, a curated remediation, and a machine fix
action. Deterministic — no patterns are invented.
Usage: ovecc diagnose [OPTIONS]
Example
$ ovecc diagnose
Diagnosis: 2 finding(s) — critical 0, high 0, medium 2, low 0
[Medium] Cyclic Dependency — component-group src/core <-> src/services (confidence 1.00)
Principle: Acyclic Dependencies Principle
Evidence: cycle_size=2 (>= 1), src/core/db.ts:2 — cycle_edge=1 (src/core -> src/services: ../services/billing), src/services/billing.ts:1 — cycle_edge=2 (src/services -> src/core: ../core/db)
Fix: Break the cycle: invert one dependency or extract the shared core both sides depend on. [Dependency Inversion / Extract shared module]
Action: break_cycle (auto-fixable: no)
When not to act: Type-only/deferred imports are excluded; a tightly cohesive cluster may be intentional.
[Medium] Unstable Dependency — component src/core (confidence 0.95)
Principle: Stable Dependencies Principle
Evidence: uphill_share=1 (>= 0.30), instability=0.25
Fix: Don't depend on something more likely to change than you: invert the dependency or introduce a stable abstraction. [Dependency Inversion / Introduce stable interface]
Action: invert_dependency (auto-fixable: no)
When not to act: Depending on a stable, well-versioned boundary is fine.
An empty diagnosis is explicit: Diagnosis: 0 finding(s) with per-severity counts.
Anatomy of a finding
| Field | Meaning |
|---|---|
| Detector + component | Which smell, where (directory granularity) |
| Principle | The established design principle it violates |
| Evidence | The metric values and file:line edges that triggered it — with the thresholds shown inline |
| Confidence | Deterministic 0–1 score derived from how far past the threshold the evidence is |
| Fix | A curated remediation, with the pattern name in brackets |
| Action | Machine-readable remediation id (consumed by agents) |
| When not to act | The honest escape hatch: cases where the smell is intentional |
Options
| Option | Effect |
|---|---|
--target <substr> | Scope to findings touching this file or module |
--severity <level> | Only findings at or above this severity |
--group-by <family|severity|component> | Group the text/markdown report — family is structural / stability / size / evolutionary |
--fail-on <medium|high|any> | Exit 1 when a finding crosses the threshold |
Plus the global options. Formats additionally
include sarif and codeclimate.
Detector families
- Structural — cyclic dependencies, hub-like components, dense structure
- Stability — unstable dependencies, zone of pain (distance from the main sequence), unstable interfaces
- Size — god components
- Evolutionary — hotspots, change coupling (requires Git history)
Thresholds are tunable via [diagnose] min_confidence in the
configuration.