MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / build_report

Function build_report

atomic-cli/src/commands/triage/project.rs:80–750  ·  view source on GitHub ↗

Build the canonical triage report for `feature` relative to `target`.

(
    repo: &Repository,
    feature: &str,
    target: &str,
)

Source from the content-addressed store, hash-verified

78
79/// Build the canonical triage report for `feature` relative to `target`.
80pub fn build_report(
81 repo: &Repository,
82 feature: &str,
83 target: &str,
84) -> Result<TriageReport, CliError> {
85 // 1. The candidate set (T0): only-in-feature, closure additions, baggage.
86 let set = repo
87 .triage_candidate_set(feature, target)
88 .map_err(CliError::Repository)?;
89
90 // 2. The pinned view Merkle (the materialized state the report is about).
91 let view_merkle = repo
92 .get_view_info(feature)
93 .map_err(CliError::Repository)?
94 .state_base32();
95
96 // Promotion scope: an unreviewed change BLOCKS promotion into a shared
97 // view, but is only a warning into a draft. Resolved once here.
98 let target_is_shared = repo
99 .get_view_info(target)
100 .map_err(CliError::Repository)?
101 .scope
102 .is_shared();
103
104 // 3. The change → intent join.
105 //
106 // The change's modified files come from the change itself
107 // (`change_modified_paths`) — authoritative and present WITHOUT any KG
108 // enrichment. Only the intent side of the join (TOUCHES/HAS_TASK/SATISFIES,
109 // projected on `vault sync`) is read from the KG, so a change is orphaned
110 // iff no intent's task touches one of its files — never merely because
111 // `atomic vault query enrich` has not run.
112 //
113 // intent_to_changes: KG intent id → candidate hashes that reach it.
114 // ac_to_changes: KG ac id → candidate hashes that satisfy it.
115 let mut change_reports: Vec<ChangeReport> = Vec::new();
116 let mut intent_to_changes: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
117 let mut ac_to_changes: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
118 let mut reached_any_intent: HashMap<String, bool> = HashMap::new();
119 let mut all_modified_files: HashSet<String> = HashSet::new();
120 // Raw modified paths per candidate hash (for the actionable orphan message).
121 let mut change_raw_paths: HashMap<String, Vec<String>> = HashMap::new();
122 // Entities defined in each candidate's modified files (parallel to
123 // `change_reports`) — the seeds for the blast-radius walk below.
124 let mut change_entities: Vec<Vec<String>> = Vec::new();
125
126 for full in &set.only_in_feature {
127 let hash = Hash::from_base32(full.as_bytes());
128
129 // Authoritative modified paths straight from the change's file_ops —
130 // no KG `MODIFIES` edge (hence no `atomic vault query enrich`) required.
131 let paths: Vec<String> = hash
132 .map(|h| repo.change_modified_paths(&h).unwrap_or_default())
133 .unwrap_or_default();
134 change_raw_paths.insert(full.clone(), paths.clone());
135
136 // Review context straight from the loaded change (best-effort): commit
137 // message, per-file hunk summaries (the `atomic change` view), the REAL

Callers 6

runMethod · 0.85
remediation_reportFunction · 0.85
report_with_intentFunction · 0.85
review_gate_reportFunction · 0.85

Calls 15

hunk_display_summariesFunction · 0.85
build_change_diffFunction · 0.85
kind_isFunction · 0.85
load_provenance_compactFunction · 0.85
load_intent_nodeFunction · 0.85
validate_intentFunction · 0.85
intent_substance_hashFunction · 0.85
load_intent_done_pinFunction · 0.85
triage_referenceFunction · 0.85
triage_candidate_setMethod · 0.80
state_base32Method · 0.80