Skip to main content

lean_ctx/tools/
ctx_index.rs

1use std::path::Path;
2
3#[must_use]
4pub fn handle(action: &str, project_root: &Path) -> String {
5    match action {
6        "status" => {
7            crate::core::index_orchestrator::status_json(project_root.to_string_lossy().as_ref())
8        }
9        "build" => {
10            crate::core::index_orchestrator::ensure_all_background(
11                project_root.to_string_lossy().as_ref(),
12            );
13            "started".to_string()
14        }
15        "build-full" => {
16            // Force rebuild by deleting existing on-disk indexes first.
17            let bm25 = crate::core::bm25_index::BM25Index::index_file_path(project_root);
18            let _ = std::fs::remove_file(&bm25);
19            // #696 C4: purge the property graph (graph.db + wal/shm + meta) and
20            // any retired JSON/call-graph artifacts so the rebuild starts clean.
21            crate::core::graph_index::purge_index(project_root.to_string_lossy().as_ref());
22            // Purge old embeddings so the full rebuild starts from scratch.
23            let vectors_dir = crate::core::index_namespace::vectors_dir(project_root);
24            let _ = std::fs::remove_file(vectors_dir.join("embeddings.bin"));
25            let _ = std::fs::remove_file(vectors_dir.join("embeddings.json"));
26            crate::core::index_orchestrator::ensure_all_background(
27                project_root.to_string_lossy().as_ref(),
28            );
29            // Build semantic index on top of the fresh BM25.
30            crate::core::index_orchestrator::build_semantic(
31                project_root.to_string_lossy().as_ref(),
32            );
33            // #420: a forced rebuild must drop the in-process call-graph cache so
34            // ctx_impact/graph reads re-derive from the fresh on-disk index
35            // instead of the pre-rebuild snapshot (the CLI path does the same).
36            crate::core::graph_cache::invalidate(Some(project_root.to_string_lossy().as_ref()));
37            "started".to_string()
38        }
39        "build-semantic" => {
40            // Build semantic index; auto-build BM25 first if missing.
41            let root = project_root.to_string_lossy();
42            let disk = crate::core::index_orchestrator::disk_status(&root);
43            if !disk.bm25_index.exists {
44                crate::core::index_orchestrator::ensure_all_background(&root);
45            }
46            crate::core::index_orchestrator::build_semantic(&root);
47            let sem = crate::core::index_orchestrator::semantic_summary(&root);
48            match sem.state {
49                "ready" => "semantic index ready".to_string(),
50                "failed" => format!(
51                    "semantic index failed: {}",
52                    sem.last_error.unwrap_or_else(|| "unknown".to_string())
53                ),
54                _ => sem
55                    .note
56                    .unwrap_or("semantic index not available".to_string()),
57            }
58        }
59        _ => "Unknown action. Use: status, build, build-full, build-semantic".to_string(),
60    }
61}