ovecc components
Recovers subsystems from the dependency graph with ACDC's two-phase clustering (Tzerpos & Holt, WCRE 2000), as a second view beside the directory-derived modules — not a replacement for them.
Usage: ovecc components [OPTIONS]
Module names come from the folder tree, so your layout decides the structure ovecc reports. This command asks the graph instead: if nobody had chosen the directories, what subsystems would the imports themselves describe? Where the two views disagree is the reportable fact.
How it clusters
Phase one applies subsystem patterns:
| Pattern | Claims |
|---|---|
| body-header | Folds x.c / x.h into one unit |
| support-library | Files whose in-degree exceeds --support-in-degree — used by everything, dominated by nothing |
| subgraph-dominator | For each file, everything reachable only through it |
Phase two adopts the leftovers into whichever subsystem they are most connected to.
The output is a containment tree, not a flat partition, and split_modules names
every module the two views disagree about.
Example
$ ovecc components
Components: 34 subsystem(s) recovered, 14 module(s) named by directory
91 file(s) claimed by a pattern, 38 adopted
Modules the layout collapses (7):
ovecc-db -> 2 subsystems: crates/ovecc-db, crates/ovecc-db/src/lib.rs
ovecc-graph -> 3 subsystems: crates/ovecc-cli/src/commands/mod.rs, crates/ovecc-graph/src/lib.rs, crates/ovecc-indexer/src/lib.rs
<support> [support library] 4 file(s), 1 adopted, modules: ovecc-cli, ovecc-core
crates/ovecc-indexer/src/lib.rs [subgraph dominator] 17 file(s), 6 adopted, modules: ovecc-cli, ovecc-core, ovecc-dataflow, ovecc-graph, ovecc-indexer, ovecc-parser, ovecc-rules
contains: crates/ovecc-graph/src/lib.rs, crates/ovecc-parser/src/lib.rs
crates/ovecc-graph/src/lib.rs [subgraph dominator] 2 file(s), modules: ovecc-graph
inside: crates/ovecc-indexer/src/lib.rs
contains and inside are the containment tree the flat module list cannot express.
Determinism
The published algorithm leaves tie-breaking unspecified — which is why the ICSE 2015 comparison had to run it five times per subject and report the best score. Here ties break on connectivity, then cardinality, then name, so one index always yields one clustering, byte for byte.
What it will not tell you
A feature with a single barrel index.ts is one subsystem, however many slices it
contains — even when those slices import each other in a cycle. Nothing outside the
feature imports the slices directly, so the barrel dominates them all.
That is a property of dominance, not a bug, and it is pinned by tests rather than left for
you to discover. For the slice-level question use diagnose
(directory granularity) or raise [architecture] module_depth. The two commands answer
different questions.
Accuracy against a published ground truth has not been measured for this implementation, so the command makes no accuracy claim. Treat it as a second opinion that is cheap to consult, not an authority that overrides your layout.
Options
| Option | Effect |
|---|---|
--target <substr> | Scope to subsystems whose name, files, or modules mention this |
--max-size <n> | Largest file count a dominator subsystem may claim (default 20) |
--support-in-degree <n> | In-degree above which a file counts as a support library (default 20) |
Plus the global options.
Counts stay whole-repository under --target, so a scoped view still says what it is a
slice of.
Related
diagnose— the same components, judged for smellsmetrics— the per-component numbersarchitecture suggest— recognition against known archetypes instead