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

Function build_report

atomic-cli/src/commands/triage/project.rs:88–825  ·  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

86
87/// Build the canonical triage report for `feature` relative to `target`.
88pub fn build_report(
89 repo: &Repository,
90 feature: &str,
91 target: &str,
92) -> Result<TriageReport, CliError> {
93 // 1. The candidate set (T0): only-in-feature, closure additions, baggage.
94 let set = repo
95 .triage_candidate_set(feature, target)
96 .map_err(CliError::Repository)?;
97
98 // 2. The pinned view Merkle (the materialized state the report is about).
99 let view_merkle = repo
100 .get_view_info(feature)
101 .map_err(CliError::Repository)?
102 .state_base32();
103
104 // Promotion scope: an unreviewed change BLOCKS promotion into a shared
105 // view, but is only a warning into a draft. Resolved once here.
106 let target_is_shared = repo
107 .get_view_info(target)
108 .map_err(CliError::Repository)?
109 .scope
110 .is_shared();
111
112 // 3. The change → intent join.
113 //
114 // The change's modified files come from the change itself
115 // (`change_modified_paths`) — authoritative and present WITHOUT any KG
116 // enrichment. Only the intent side of the join (TOUCHES/HAS_TASK/SATISFIES,
117 // projected on `vault sync`) is read from the KG, so a change is orphaned
118 // iff no intent's task touches one of its files — never merely because
119 // `atomic vault query enrich` has not run.
120 //
121 // intent_to_changes: KG intent id → candidate hashes that reach it.
122 // ac_to_changes: KG ac id → candidate hashes that satisfy it.
123 let mut change_reports: Vec<ChangeReport> = Vec::new();
124 let mut intent_to_changes: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
125 let mut ac_to_changes: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
126 let mut reached_any_intent: HashMap<String, bool> = HashMap::new();
127 let mut all_modified_files: HashSet<String> = HashSet::new();
128 // Raw modified paths per candidate hash (for the actionable orphan message).
129 let mut change_raw_paths: HashMap<String, Vec<String>> = HashMap::new();
130 // Entities defined in each candidate's modified files (parallel to
131 // `change_reports`) — the seeds for the blast-radius walk below.
132 let mut change_entities: Vec<Vec<String>> = Vec::new();
133 // Walkthrough facts, collected in the same KG passes (no extra queries):
134 // path → module (PART_OF) and file → file dependency edges (IMPORTS/
135 // INCLUDES). Best-effort — empty on an unenriched KG.
136 let mut file_module: BTreeMap<String, String> = BTreeMap::new();
137 let mut file_deps: BTreeSet<(String, String)> = BTreeSet::new();
138 // Task facts from reached intents (id, text, touches, satisfies), in
139 // intent-id order — the walkthrough's narrative inputs.
140 let mut task_facts: Vec<TaskFact> = Vec::new();
141
142 for full in &set.only_in_feature {
143 let hash = Hash::from_base32(full.as_bytes());
144
145 // Authoritative modified paths straight from the change's file_ops —

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
is_vault_pathFunction · 0.85
triage_referenceFunction · 0.85
build_walkthroughFunction · 0.85