Deduplicate project docs by content

CLAUDE.md is often symlinked to AGENTS.md, causing identical content
to be loaded twice and wasting ~50% of the 32KB budget. Track seen
content in a HashSet and skip duplicates before the budget check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-09 13:58:20 -04:00
parent f965467af0
commit 8f929a855c

View file

@ -1,5 +1,6 @@
use crate::sandbox::Sandbox;
use arc_llm::provider::Provider;
use std::collections::HashSet;
use tracing::{debug, info, warn};
const BUDGET_BYTES: usize = 32768;
@ -26,6 +27,7 @@ pub async fn discover_project_docs(
let mut results = Vec::new();
let mut budget_remaining = BUDGET_BYTES;
let mut seen_content = HashSet::new();
for dir in &directories {
for filename in &candidate_filenames {
@ -35,6 +37,10 @@ pub async fn discover_project_docs(
warn!(path = %path, "Project doc file empty, skipping");
continue;
}
if !seen_content.insert(content.clone()) {
debug!(path = %path, "Project doc duplicate content, skipping");
continue;
}
if content.len() <= budget_remaining {
debug!(path = %path, size_bytes = content.len(), "Project doc loaded");
budget_remaining -= content.len();
@ -184,6 +190,35 @@ mod tests {
assert!(docs[0].len() + docs[1].len() <= BUDGET_BYTES);
}
#[tokio::test]
async fn deduplicates_symlinked_files() {
let mut files = HashMap::new();
files.insert("/repo/AGENTS.md".into(), "shared instructions".into());
files.insert("/repo/CLAUDE.md".into(), "shared instructions".into());
let env: Arc<dyn Sandbox> = Arc::new(MockSandbox {
files,
..Default::default()
});
let docs = discover_project_docs(env.as_ref(), "/repo", "/repo", Provider::Anthropic).await;
assert_eq!(docs.len(), 1);
assert_eq!(docs[0], "shared instructions");
}
#[tokio::test]
async fn deduplicates_across_directories() {
let mut files = HashMap::new();
files.insert("/repo/AGENTS.md".into(), "shared instructions".into());
files.insert("/repo/src/AGENTS.md".into(), "shared instructions".into());
let env: Arc<dyn Sandbox> = Arc::new(MockSandbox {
files,
..Default::default()
});
let docs =
discover_project_docs(env.as_ref(), "/repo", "/repo/src", Provider::Anthropic).await;
assert_eq!(docs.len(), 1);
assert_eq!(docs[0], "shared instructions");
}
#[tokio::test]
async fn walks_directory_hierarchy() {
let mut files = HashMap::new();