Module architecture_metrics
Expand description
architecture-metrics analysis — repo-level structural-health
numbers over the resolved import graph, the kind you trend over time.
propagation_cost(MacCormack, Rusnak & Baldwin 2006) — the density of the visibility (transitive-closure) matrix: “a change to a random file can, on average, reach this fraction of the system”.acd— Lakos’s Average Component Dependency: the mean number of files each file depends on directly or transitively (incl. self).nccd— Normalised Cumulative Component Dependency:CCDdivided by theCCDof a balanced binary tree of the same size.< 1≈ horizontal/flat,> 1≈ vertical/layered,> 2≈ likely cyclic (Lakos 1996, Large-Scale C++ Software Design).dependency_cycles/largest_cycle— count of non-trivial SCCs and the size of the biggest tangle.architecture_type—hierarchical(acyclic),core-periphery(one dominant cyclic group), ormulti-core(several comparable ones) — Baldwin,MacCormack& Rusnak 2014.
All derived in one pass from the shared import-graph kernel (SCC + reachability), so this adds no new query cost beyond building the graph. Accuracy follows the import resolver’s language coverage.
Four further rows disclose how much of the import surface the graph
above actually covers — coverage transparency, not defect scores, so
that a sparse graph can’t read as a clean one. The structural metrics
only ever see the resolved edges (target_path IS NOT NULL); these
query the full imports table so a poor resolution rate is visible:
import_resolution_rate— fraction of all import statements whose target resolved to an in-repo file. External and standard-library imports (numpy,java.util,std::fmt, …) legitimately point outside the repo and count as unresolved, so a repo with many third-party dependencies naturally scores lower — this is expected, not a resolver bug.first_party_import_share— fraction of import statements that are first-party by intent: either already resolved, or a relative import (use crate::…,from .mod import …,./foo) naming an in-repo path even when the resolver missed it — including a first-party glob (use crate::foo::*;, bareuse super::*;), whichimports.kindtagswildcardrather thanrelative(see the “Definition caveat” below) but which is still unambiguously in-repo by itscrate::/self::/super::prefix.resolution_rate_first_party— of those first-party imports, the fraction that resolved. It drops external imports from the denominator, isolating resolver coverage from third-party-dependency density: a low value points at a genuine resolver gap rather than many external deps.wildcard_import_share— fraction of all import statements that are glob imports (imports.kind = 'wildcard'), first-party or not. Purely informational (a glob names a module, not a symbol).
When an active calibration artifact (crate::calibration::load_active_artifact)
carries a repo_metrics section (corpus pools populated by codelore calibrate), additional rows report where this repo’s propagation_cost
and cycle_file_share sit against that corpus, each paired with a Wilson
95% confidence interval (…:ci_low / …:ci_high) that reflects the finite
corpus pool’s sampling uncertainty — see run_architecture_metrics.
Absent artifact or absent section ⇒ those rows are simply not emitted (the
additivity contract this module’s tests pin).
Structs§
- Architecture
Metric Row - One repo-level architecture metric:
(metric, value). The value is a string so the numeric metrics and the textualarchitecture_typelabel can share one row shape; numeric values are written as bare, parseable numbers (e.g.0.0607) so downstream tooling can read them.
Functions§
- run_
architecture_ metrics - Run the
architecture-metricsanalysis. Returns one row per repo-level metric, in a fixed presentation order, plus the import-resolution disclosure rows (see [import_resolution_rows]). Returns just those disclosure rows when the repo has import statements but none resolve into the graph (n == 0); empty only when the repo has no imports at all.