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

Function consolidate

atomic-agent/src/provenance/consolidate.rs:67–119  ·  view source on GitHub ↗

Consolidate raw tool nodes into Decision nodes. Scans the graph for recognizable sequences of unclassified tool nodes and replaces each sequence with a single `Decision` node that references the originals via `consolidated_from`. The original nodes are preserved in the graph (they keep their edges) — the decision node is appended alongside them with new edges linking it to the sequence's context.

(
    nodes: &mut Vec<GraphNode>,
    edges: &mut Vec<GraphEdge>,
    stats: &mut GraphStats,
    counter: &mut u64,
    session_prefix: &str,
)

Source from the content-addressed store, hash-verified

65///
66/// Returns the number of decision nodes created.
67pub fn consolidate(
68 nodes: &mut Vec<GraphNode>,
69 edges: &mut Vec<GraphEdge>,
70 stats: &mut GraphStats,
71 counter: &mut u64,
72 session_prefix: &str,
73) -> u32 {
74 let mut created = 0;
75
76 // Collect sequences of unclassified tool-derived nodes between
77 // structural boundaries (goals, patches, human gates).
78 let sequences = find_sequences(nodes);
79
80 for seq in sequences {
81 if seq.len() < 2 {
82 continue;
83 }
84
85 // Try each pattern in priority order. First match wins.
86 let decision = detect_backtracking(nodes, &seq, counter, session_prefix)
87 .or_else(|| detect_test_driven_iteration(nodes, &seq, counter, session_prefix))
88 .or_else(|| detect_full_cycle(nodes, &seq, counter, session_prefix))
89 .or_else(|| detect_commit_and_verify(nodes, &seq, counter, session_prefix))
90 .or_else(|| detect_informed_commit(nodes, &seq, counter, session_prefix))
91 .or_else(|| detect_systematic_exploration(nodes, &seq, counter, session_prefix));
92
93 if let Some((decision_node, decision_edges)) = decision {
94 let decision_id = decision_node.id.clone();
95
96 // Collect the IDs of original nodes before mutating the vec.
97 let original_ids: Vec<String> = seq.iter().map(|&i| nodes[i].id.clone()).collect();
98
99 stats.increment(NodeKind::Decision);
100 stats.edge_count += decision_edges.len() as u32;
101 nodes.push(decision_node);
102 edges.extend(decision_edges);
103
104 // Mark the original nodes as consolidated.
105 for target_id in &original_ids {
106 if let Some(node) = nodes.iter_mut().find(|n| n.id == *target_id) {
107 node.classified = true;
108 if node.consolidated_from.is_empty() {
109 node.consolidated_from = vec![decision_id.clone()];
110 }
111 }
112 }
113
114 created += 1;
115 }
116 }
117
118 created
119}
120
121// =============================================================================
122// Sequence Finding

Callers 2

run_consolidateFunction · 0.85
consolidateMethod · 0.85

Calls 15

find_sequencesFunction · 0.85
detect_backtrackingFunction · 0.85
detect_full_cycleFunction · 0.85
detect_commit_and_verifyFunction · 0.85
detect_informed_commitFunction · 0.85
extendMethod · 0.80
iter_mutMethod · 0.80
lenMethod · 0.45
cloneMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected