pub struct ImpactClosureFacts {
pub affected_count: usize,
pub affected_not_shown: Vec<String>,
pub affected_by_dir: Vec<AffectedDirectory>,
pub affected_by_dir_omitted: usize,
pub coordination_gap: Vec<CoordinationGapFact>,
pub co_change_gap: Vec<CoChangeGapFact>,
pub co_change_gap_count: usize,
pub search_gap: Option<SearchGapFacts>,
}Expand description
Stage 3 of the brief: the impact closure. The transitive affected-but-not-in-diff set plus the coordination gap. The differentiator a diff tool fundamentally cannot do, because it has no graph.
Honest scope (ADR-001, syntactic): the coordination gap is an attention pointer at the exact inter-module failure mode, NOT a correctness proof.
Fields§
§affected_count: usizeThe FULL number of files transitively affected by the changeset
(reverse-deps + re-export chains) that are NOT in the diff. Computed
BEFORE affected_not_shown is capped to a
sample, so it is always the true magnitude of the blast radius.
affected_not_shown: Vec<String>A capped, path-sorted sample of the affected root-relative paths (at most
AFFECTED_SAMPLE_CAP), deduped. The full count lives in
affected_count and the distribution in
affected_by_dir; use this list to jump to
representative files, NEVER to enumerate the blast radius or to infer its
shape. Because it is a prefix of the sorted set, it clusters in whichever
directory sorts first. To reconstruct the full set, run
fallow check --impact-closure <path> once per changed file and union the
results: that flag seeds from a single file, so no single command
reproduces this changeset-wide union.
affected_by_dir: Vec<AffectedDirectory>The blast radius rolled up by parent directory: how the affected files
distribute, heaviest directory first, ties broken by directory path so the
order is deterministic. This is the SHAPE signal, and unlike
affected_not_shown its counts are exact for
every directory it lists. At most AFFECTED_DIR_CAP entries.
affected_by_dir_omitted: usizeHow many directories did not fit within AFFECTED_DIR_CAP and are
absent from affected_by_dir. They are the
lightest ones; their files are still counted in
affected_count. Zero when nothing was omitted.
Add this to affected_by_dir.len() for the true number of directories
the change reaches.
coordination_gap: Vec<CoordinationGapFact>Coordination gaps: a changed file exports a contract consumed by a module
absent from the diff. One entry per (changed file, consumer) pair. NOT a
subset of affected_not_shown: the gap
deliberately skips story and test consumers that the affected set counts.
co_change_gap: Vec<CoChangeGapFact>Co-change gaps: a changed file has a hidden change-coupling partner
that is absent from the diff. The two files changed together in most
commits of the history window, but no import or re-export chain
connects them, so the graph facts above cannot point at the partner.
Advisory, never gates. Omitted when empty.
At most 10 entries (CO_CHANGE_GAP_CAP), strongest degree first.
co_change_gap_count: usizeAll co-change gaps, before the cap cuts co_change_gap. Omitted
when zero.
search_gap: Option<SearchGapFacts>Consumers that a whole-word text search for a changed export name does
not find (missed), or finds only under another local name
(renamed). Only exports whose declaration statement overlaps an added
diff line count, and only consumers outside the diff. Absent when no
such consumer exists.
Implementations§
Source§impl ImpactClosureFacts
impl ImpactClosureFacts
Sourcepub fn set_co_change_gaps(&mut self, gaps: &[CoChangeGapFact])
pub fn set_co_change_gaps(&mut self, gaps: &[CoChangeGapFact])
Set the co-change gaps: keep the first CO_CHANGE_GAP_CAP entries
and record the full count.
Sourcepub fn new(
affected: &[String],
coordination_gap: Vec<CoordinationGapFact>,
) -> Self
pub fn new( affected: &[String], coordination_gap: Vec<CoordinationGapFact>, ) -> Self
Build the facts from the full closure, capping the file sample and the directory rollup while preserving the exact total.
affected must arrive deduped and path-sorted (the engine closure
guarantees both); the sample is its prefix.