Anchor code learnings to the CRDT graph using FileOps from the recorded change. This is a post-processing step called after the LLM returns human-readable findings. For each `CodeLearning`, it looks up the file path and line number in the change's `FileOps` to find the corresponding TrunkId, BranchId, and LeafId references. # Arguments `learnings` — The code learnings to anchor (modified in pla
(learnings: &mut [CodeLearning], file_ops: &[atomic_core::change::FileOps])
| 305 | /// - If no match is found, the anchor is left as `None` (the learning still |
| 306 | /// works, just without auto-tracking through renames/refactors) |
| 307 | pub fn anchor_to_graph(learnings: &mut [CodeLearning], file_ops: &[atomic_core::change::FileOps]) { |
| 308 | for learning in learnings.iter_mut() { |
| 309 | let mut anchor = GraphAnchor::empty(); |
| 310 | |
| 311 | // Find the matching file in FileOps |
| 312 | for fop in file_ops { |
| 313 | if fop.path() != learning.path { |
| 314 | continue; |
| 315 | } |
| 316 | |
| 317 | // Set trunk anchor (file level) |
| 318 | let tid = fop.trunk_id(); |
| 319 | anchor.trunk = Some((tid.change_id().get(), tid.file_idx())); |
| 320 | |
| 321 | // If we have a line number, try to match line operations |
| 322 | if let Some(target_line) = learning.line { |
| 323 | for line_op in fop.line_ops() { |
| 324 | // Check both old and new line numbers — deletes have old, |
| 325 | // inserts have new, some ops have both |
| 326 | let op_line = line_op.new_line_num().or_else(|| line_op.old_line_num()); |
| 327 | let matches = match (op_line, learning.end_line) { |
| 328 | (Some(l), Some(end)) => l as u32 >= target_line && (l as u32) <= end, |
| 329 | (Some(l), None) => l as u32 == target_line, |
| 330 | (None, _) => false, |
| 331 | }; |
| 332 | |
| 333 | if matches { |
| 334 | let bid = line_op.branch_id(); |
| 335 | anchor |
| 336 | .branches |
| 337 | .push((bid.change_id().get(), bid.branch_idx())); |
| 338 | |
| 339 | // Collect leaf IDs from the line's operations |
| 340 | for leaf_op in line_op.leaf_ops() { |
| 341 | if let Some(lid) = leaf_op_id(leaf_op) { |
| 342 | anchor.leaves.push(lid); |
| 343 | } |
| 344 | } |
| 345 | } |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | break; // Found the file, done |
| 350 | } |
| 351 | |
| 352 | if anchor.is_populated() { |
| 353 | learning._anchor = Some(anchor); |
| 354 | } |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | // CRDT Anchor Helpers |
| 359 |
no test coverage detected