Module coupling
Expand description
Change-coupling analysis per spec §3.2.1 correctness invariants:
- max-changeset-size pre-filter (drops huge commits)
- Mirrored pair dedup via
path_a < path_b - Empty-changeset filter (implicit — commits with 0 files produce no pairs)
min_revsfilter (per-file)min_shared_revsfilter (per-pair)min_coupling_pctfilter (degree threshold)- Fisher exact significance test (p <
fisher_significance, default 0.05)
The Fisher test guards against spurious coupling from refactor sweeps that 2025 MSR research identified as the dominant noise source.
Research basis: see docs/research-foundations.md entry “coupling”
(Gall, Hajek & Jazayeri, ICSM 1998 — original logical-coupling paper;
Tornhill, Your Code as a Crime Scene, 2015 — productisation).
Structs§
- Coupling
Absence - A historically-coupled partner missing from a change set. Produced by
compute_coupling_absencesfor both the PR-scopeddiffsurface and the working-tree change-set engine. - Coupling
Memo Key - Memo key for
run_coupling. Carries EXACTLY theOptionsfields thatbuild_coupling_sql,good_commits_cte,source_table,build_total_commits_sql, or the Rust-side Fisher pass branch on — and nothing else. TwoOptionsthat agree on every field here produce a byte-identical un-row-limited result, so they may share a memo entry. - Coupling
Row - A single coupling pair produced by
run_coupling.
Functions§
- compute_
coupling_ absences - Flag every coupling pair where exactly one side is in the changed set: the touched file’s historically-coupled partner is absent, which is the signal a co-change was forgotten. Advisory — callers decide severity.
- count_
coupling_ nodes - Count the number of nodes in the behavioral coupling graph universe.
Returns the count of distinct files in the same
file_revscandidate set used byrun_coupling— i.e. files withrevs >= opts.min_revsafter the configured--time-bucket/--use-canonical-lineagerewrite. Honoursopts.max_changeset_sizevia the samegood_commitspre-filter so isolated nodes inside large commits don’t inflate the denominator ofdensity. - density
- Density of the behavioral coupling graph:
2·E / (V·(V−1)), in[0, 1]. - partner_
index - Build a bidirectional partner index from coupling rows: for each
file, the set of files it is Fisher-significantly coupled with. The
structure×history fusion analyses (
unstable-interface,crossing) intersect this with the import graph, so the construction lives here next toCouplingRowrather than being re-derived in each. - run_
coupling - Run change-coupling analysis over the ingested fact store.
- run_
coupling_ scoped - Scoped variant of
run_coupling: reads change history fromchanges_sourceinstead of the opt-derived table. Used when a caller has already materialized a date-filtered view (changes_at_ts) and wants coupling restricted to that window. Does NOT memoize — the custom source is not covered by the standardCouplingMemoKey.