Skip to main content

dev_prune/
tools.rs

1// Copyright 2026 VKrishna04
2// SPDX-License-Identifier: Apache-2.0
3
4// Report-only footprint of AI-assistant tools that leave large, expensive-to-rebuild
5// output behind in a repository, so they belong nowhere near the adapter system.
6//
7// A `PackageManager` adapter exists because a lockfile proves the directory it deletes
8// can be rebuilt for the cost of a network download. graphify's `graphify-out/` and
9// understand-anything's `.understand-anything/` have no such proof: rebuilding either
10// means re-running the tool's own extraction passes, LLM calls included, so there is
11// nothing here for `devp run` to verify or delete. `devp status` reports the size so it
12// is not a mystery, and stops there.
13
14use std::path::{Path, PathBuf};
15
16use crate::adapters::dir_size;
17use crate::constants;
18
19/// One tool's output directory found at a repository's root, and its size on disk.
20#[derive(Debug, Clone)]
21pub struct ToolFootprint {
22    pub name: &'static str,
23    pub path: PathBuf,
24    pub size_bytes: u64,
25}
26
27/// Look for graphify's and understand-anything's output directories at the root of
28/// `repo_root`, in exactly those two names, nothing walked or guessed.
29pub fn scan(repo_root: &Path) -> Vec<ToolFootprint> {
30    let candidates = [
31        ("graphify", constants::GRAPHIFY_OUTPUT_DIR),
32        ("understand-anything", constants::UNDERSTAND_ANYTHING_DIR),
33    ];
34
35    candidates
36        .into_iter()
37        .filter_map(|(name, dir_name)| {
38            let path = repo_root.join(dir_name);
39            path.is_dir().then(|| ToolFootprint {
40                name,
41                size_bytes: dir_size(&path),
42                path,
43            })
44        })
45        .collect()
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn finds_only_directories_that_exist() {
54        let dir = tempfile::tempdir().unwrap();
55        assert!(scan(dir.path()).is_empty());
56
57        std::fs::create_dir(dir.path().join(constants::GRAPHIFY_OUTPUT_DIR)).unwrap();
58        std::fs::write(
59            dir.path()
60                .join(constants::GRAPHIFY_OUTPUT_DIR)
61                .join("graph.json"),
62            b"{}",
63        )
64        .unwrap();
65
66        let found = scan(dir.path());
67        assert_eq!(found.len(), 1);
68        assert_eq!(found[0].name, "graphify");
69        assert_eq!(found[0].size_bytes, 2);
70    }
71
72    #[test]
73    fn finds_both_when_both_present() {
74        let dir = tempfile::tempdir().unwrap();
75        std::fs::create_dir(dir.path().join(constants::GRAPHIFY_OUTPUT_DIR)).unwrap();
76        std::fs::create_dir(dir.path().join(constants::UNDERSTAND_ANYTHING_DIR)).unwrap();
77
78        let found = scan(dir.path());
79        assert_eq!(found.len(), 2);
80    }
81}