use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::io::{BufRead, BufReader, Write};
use std::path::{Component, Path, PathBuf};
use std::time::UNIX_EPOCH;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
const PROTOCOL: &str = "2024-11-05";
const QUERY_MAGIC: &[u8; 7] = b"RDARQ2\n";
const SOURCE_MAGIC: &[u8; 7] = b"RDARS2\n";
const MAX_MESSAGE_BYTES: usize = 16 * 1024 * 1024;
const MAX_SOURCE_PACKET_BYTES: usize = 12 * 1024;
#[derive(Clone, Copy, Debug)]
enum Framing {
Newline,
ContentLength,
}
fn read_bounded_line(reader: &mut impl BufRead, line: &mut Vec<u8>) -> std::io::Result<usize> {
line.clear();
loop {
let chunk = reader.fill_buf()?;
if chunk.is_empty() {
return Ok(line.len());
}
let amount = chunk
.iter()
.position(|byte| *byte == b'\n')
.map_or(chunk.len(), |index| index + 1);
if line.len().saturating_add(amount) > MAX_MESSAGE_BYTES {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"MCP frame exceeds 16 MiB limit",
));
}
let terminated = chunk[..amount].last() == Some(&b'\n');
line.extend_from_slice(&chunk[..amount]);
reader.consume(amount);
if terminated {
return Ok(line.len());
}
}
}
fn read_message(reader: &mut impl BufRead) -> std::io::Result<Option<(Value, Framing)>> {
let mut first = Vec::new();
loop {
if read_bounded_line(reader, &mut first)? == 0 {
return Ok(None);
}
let first = String::from_utf8(std::mem::take(&mut first)).map_err(|_| {
std::io::Error::new(std::io::ErrorKind::InvalidData, "MCP header is not UTF-8")
})?;
let first = first.trim_end_matches(['\r', '\n']);
if first.is_empty() {
continue;
}
if let Some(value) = first.strip_prefix("Content-Length:") {
let Some(content_length) = value.trim().parse::<usize>().ok() else {
continue;
};
if content_length > MAX_MESSAGE_BYTES {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"MCP frame exceeds 16 MiB limit",
));
}
loop {
let mut header = Vec::new();
if read_bounded_line(reader, &mut header)? == 0 {
return Ok(None);
}
if header.iter().all(u8::is_ascii_whitespace) {
break;
}
}
let mut body = vec![0u8; content_length];
reader.read_exact(&mut body)?;
if let Ok(message) = serde_json::from_slice(&body) {
return Ok(Some((message, Framing::ContentLength)));
}
continue;
}
if let Ok(message) = serde_json::from_str(first) {
return Ok(Some((message, Framing::Newline)));
}
}
}
fn write_message(out: &mut impl Write, value: &Value, framing: Framing) -> std::io::Result<()> {
let body = serde_json::to_vec(value)?;
match framing {
Framing::Newline => {
out.write_all(&body)?;
out.write_all(b"\n")?;
}
Framing::ContentLength => {
write!(out, "Content-Length: {}\r\n\r\n", body.len())?;
out.write_all(&body)?;
}
}
out.flush()
}
fn tools() -> Value {
json!([
{
"name": "navigate",
"description": "Full task once. FINAL SOURCE ANCHOR or FINAL REPOSITORY OVERVIEW is final; MAP metadata fallback.",
"inputSchema": { "type": "object", "properties": { "query": { "type": "string" } }, "required": ["query"] },
"annotations": { "readOnlyHint": true, "destructiveHint": false, "idempotentHint": true, "openWorldHint": false }
}
])
}
fn text_result(text: String) -> Value {
json!({ "content": [{ "type": "text", "text": text }] })
}
fn compact_metadata_list(value: &str) -> Option<(String, usize)> {
const PREVIEW_ITEMS: usize = 6;
let inner = value.strip_prefix('[')?.strip_suffix(']')?;
let items: Vec<&str> = inner
.split(',')
.map(str::trim)
.filter(|item| !item.is_empty())
.collect();
let preview = items
.iter()
.take(PREVIEW_ITEMS)
.copied()
.collect::<Vec<_>>()
.join(", ");
Some((
format!("[{preview}]"),
items.len().saturating_sub(PREVIEW_ITEMS),
))
}
fn map_metadata_head(reader: &mut impl BufRead) -> std::io::Result<String> {
const MAX_BYTES: usize = 64 * 1024;
let invalid = || std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid MAP metadata");
let mut line = String::new();
if reader.read_line(&mut line)? == 0 || line.trim_end_matches(['\r', '\n']) != "---" {
return Err(invalid());
}
let mut metadata = crate::frontmatter::Frontmatter::new();
let mut bytes = line.len();
loop {
line.clear();
if reader.read_line(&mut line)? == 0 {
return Err(invalid());
}
bytes += line.len();
if bytes > MAX_BYTES {
return Err(invalid());
}
let value = line.trim_end_matches(['\r', '\n']);
if value == "---" {
break;
}
if value.trim().is_empty() || value.trim_start().starts_with('#') {
continue;
}
if value.starts_with([' ', '\t']) {
return Err(invalid());
}
let Some((key, value)) = value.split_once(':') else {
return Err(invalid());
};
let key = key.trim();
let value = value.trim();
if key.is_empty() || key.contains(char::is_whitespace) || value.is_empty() {
return Err(invalid());
}
if !matches!(key, "map" | "api_hash" | "kids_hash" | "stamped") {
if matches!(key, "children" | "uses") {
let Some((preview, omitted)) = compact_metadata_list(value) else {
return Err(invalid());
};
metadata.set(key, preview);
if omitted > 0 {
let omitted_key = format!("{key}_omitted");
metadata.set(&omitted_key, omitted.to_string());
}
} else {
metadata.set(key, value);
}
}
}
Ok(metadata.render())
}
fn read_map_metadata(path: &Path) -> std::io::Result<String> {
let file = std::fs::File::open(path)?;
map_metadata_head(&mut BufReader::new(file))
}
fn asks_for_package_entry(words: &[String]) -> bool {
words
.iter()
.any(|word| matches!(word.as_str(), "entry" | "entrypoint" | "main"))
&& words.iter().any(|word| {
matches!(
word.as_str(),
"package" | "module" | "subsystem" | "component"
)
})
}
fn asks_for_callers(words: &[String]) -> bool {
words
.iter()
.any(|word| word.starts_with("call") || matches!(word.as_str(), "uses" | "used"))
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct IndexedSymbol {
anchor: String,
signature: String,
public: bool,
executable: bool,
body_terms: Vec<u32>,
callers: Vec<String>,
calls: Vec<String>,
}
#[derive(Default, Serialize, Deserialize)]
struct SymbolIndex {
records: Vec<IndexedSymbol>,
by_name: BTreeMap<String, Vec<usize>>,
postings: HashMap<u32, Vec<usize>>,
}
impl SymbolIndex {
fn insert(&mut self, name: String, record: IndexedSymbol) {
let identifier = self.records.len();
let mut terms: BTreeSet<u32> = record.body_terms.iter().copied().collect();
let name_words = crate::routes::split_ident(&name);
terms.extend(
name_words
.iter()
.filter_map(|word| crate::routes::term_fingerprint(word)),
);
terms.extend(
crate::routes::normalize(&record.signature)
.iter()
.filter_map(|word| crate::routes::term_fingerprint(word)),
);
terms.extend(
record
.calls
.iter()
.flat_map(|call| crate::routes::split_ident(call))
.filter_map(|word| crate::routes::term_fingerprint(&word)),
);
terms.extend(
record
.anchor
.split_once('#')
.map_or(record.anchor.as_str(), |(path, _)| path)
.split('/')
.flat_map(crate::routes::split_ident)
.filter_map(|word| crate::routes::term_fingerprint(&word)),
);
for term in terms {
self.postings.entry(term).or_default().push(identifier);
}
self.by_name.entry(name).or_default().push(identifier);
self.records.push(record);
}
#[cfg(test)]
fn from_grouped(groups: BTreeMap<String, Vec<IndexedSymbol>>) -> Self {
let mut index = Self::default();
for (name, records) in groups {
for record in records {
index.insert(name.clone(), record);
}
}
index
}
fn candidate_ids(&self, query_words: &[String]) -> Vec<usize> {
let mut identifiers = Vec::new();
for fingerprint in query_words
.iter()
.filter_map(|word| crate::routes::term_fingerprint(word))
{
if let Some(posting) = self.postings.get(&fingerprint) {
identifiers.extend_from_slice(posting);
}
}
identifiers.sort_unstable();
identifiers.dedup();
identifiers.retain(|identifier| *identifier < self.records.len());
identifiers
}
fn is_valid(&self) -> bool {
let valid_id = |identifier: &usize| *identifier < self.records.len();
self.by_name.values().flatten().all(valid_id)
&& self.postings.values().flatten().all(valid_id)
&& self
.records
.iter()
.all(|record| record.body_terms.windows(2).all(|pair| pair[0] <= pair[1]))
}
fn rarity(&self, word: &str) -> usize {
let Some(fingerprint) = crate::routes::term_fingerprint(word) else {
return 1;
};
let Some(posting) = self.postings.get(&fingerprint) else {
return 1;
};
let ratio = self.records.len().div_ceil(posting.len()).max(1);
(1 + ratio.ilog2() as usize).min(8)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
struct StateStamp {
bytes: u64,
modified_nanos: u128,
}
#[derive(Serialize, Deserialize)]
struct QuerySnapshot {
state_stamp: Option<StateStamp>,
symbols: SymbolIndex,
overview: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct IndexedSourceFile {
path: String,
hash: [u8; 32],
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct IndexedSourceSpan {
file: u32,
line: u32,
end_line: u32,
symbol: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct SourceSnapshot {
state_stamp: Option<StateStamp>,
files: Vec<IndexedSourceFile>,
spans: Vec<IndexedSourceSpan>,
}
impl SourceSnapshot {
fn from_cache(cache: &crate::cache::ScanCache, state_stamp: Option<StateStamp>) -> Self {
let mut files = Vec::new();
let mut spans = Vec::new();
for (path, entry) in &cache.files {
let Some(lang) = entry.lang else { continue };
let Some(extraction) = cache.parses.get(&(lang, entry.hash)) else {
continue;
};
let Ok(file) = u32::try_from(files.len()) else {
break;
};
files.push(IndexedSourceFile {
path: path.clone(),
hash: entry.hash,
});
spans.extend(extraction.defs.iter().map(|definition| IndexedSourceSpan {
file,
line: definition.line,
end_line: definition.end_line,
symbol: definition.name.clone(),
}));
}
Self {
state_stamp,
files,
spans,
}
}
fn is_valid(&self) -> bool {
self.spans.iter().all(|span| {
span.line > 0
&& span.end_line >= span.line
&& !span.symbol.is_empty()
&& (span.file as usize) < self.files.len()
})
}
fn exact_task_span(&self, task: &str) -> Option<&IndexedSourceSpan> {
let words: BTreeSet<String> = task
.split(|character: char| !character.is_ascii_alphanumeric() && character != '_')
.filter(|word| !word.is_empty())
.map(str::to_ascii_lowercase)
.collect();
let mut matches = self.spans.iter().filter(|span| {
words
.iter()
.any(|word| word.eq_ignore_ascii_case(&span.symbol))
});
let first = matches.next()?;
matches.next().is_none().then_some(first)
}
}
fn query_snapshot_path(root: &Path) -> PathBuf {
crate::cache::radar_dir(root).join("query.bin")
}
fn source_snapshot_path(root: &Path) -> PathBuf {
crate::cache::radar_dir(root).join("source.bin")
}
pub fn invalidate_query_snapshot(root: &Path) {
let _ = std::fs::remove_file(query_snapshot_path(root));
let _ = std::fs::remove_file(source_snapshot_path(root));
}
fn load_query_snapshot(root: &Path) -> Option<QuerySnapshot> {
let bytes = std::fs::read(query_snapshot_path(root)).ok()?;
let payload = bytes.strip_prefix(QUERY_MAGIC)?;
let snapshot: QuerySnapshot = postcard::from_bytes(payload).ok()?;
let state_path = crate::cache::radar_dir(root).join("state.bin");
if snapshot.state_stamp != file_stamp(&state_path) || !snapshot.symbols.is_valid() {
return None;
}
Some(snapshot)
}
fn load_source_snapshot(root: &Path) -> Option<SourceSnapshot> {
let bytes = std::fs::read(source_snapshot_path(root)).ok()?;
let encoded = bytes.strip_prefix(SOURCE_MAGIC)?;
let (expected_hash, payload) = encoded.split_at_checked(32)?;
if blake3::hash(payload).as_bytes() != expected_hash {
return None;
}
let snapshot: SourceSnapshot = postcard::from_bytes(payload).ok()?;
let state_path = crate::cache::radar_dir(root).join("state.bin");
if snapshot.state_stamp != file_stamp(&state_path) || !snapshot.is_valid() {
return None;
}
Some(snapshot)
}
fn save_source_snapshot(root: &Path, snapshot: &SourceSnapshot) -> std::io::Result<()> {
let payload = postcard::to_stdvec(snapshot)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::InvalidData, error))?;
let mut checked = Vec::with_capacity(32 + payload.len());
checked.extend_from_slice(blake3::hash(&payload).as_bytes());
checked.extend_from_slice(&payload);
write_snapshot(&source_snapshot_path(root), SOURCE_MAGIC, checked)
}
fn write_snapshot(path: &Path, magic: &[u8], payload: Vec<u8>) -> std::io::Result<()> {
let mut bytes = Vec::with_capacity(magic.len() + payload.len());
bytes.extend_from_slice(magic);
bytes.extend_from_slice(&payload);
let temporary = path.with_extension("bin.tmp");
std::fs::write(&temporary, bytes)?;
std::fs::rename(temporary, path)
}
pub fn save_query_snapshot(root: &Path, cache: &crate::cache::ScanCache) -> std::io::Result<()> {
let state_stamp = file_stamp(&crate::cache::radar_dir(root).join("state.bin"));
let snapshot = QuerySnapshot {
state_stamp,
symbols: ServerState::index_symbols(cache),
overview: ServerState::overview(cache),
};
let payload = postcard::to_stdvec(&snapshot)
.map_err(|error| std::io::Error::new(std::io::ErrorKind::InvalidData, error))?;
let directory = crate::cache::radar_dir(root);
std::fs::create_dir_all(&directory)?;
write_snapshot(&query_snapshot_path(root), QUERY_MAGIC, payload)?;
let source = SourceSnapshot::from_cache(cache, state_stamp);
save_source_snapshot(root, &source)
}
#[derive(Default)]
struct OverviewScope {
files: BTreeSet<String>,
topics: BTreeSet<String>,
symbols: BTreeSet<String>,
}
fn path_topics(path: &str) -> impl Iterator<Item = String> + '_ {
path.split('/').flat_map(|component| {
let stem = component
.rsplit_once('.')
.map_or(component, |(stem, _)| stem);
crate::routes::split_ident(stem).into_iter().filter(|word| {
!matches!(
word.as_str(),
"index" | "lib" | "main" | "mod" | "src" | "test" | "tests"
)
})
})
}
fn direct_symbol_context<'a>(
entry: &crate::routes::RouteEntry,
symbols: &'a SymbolIndex,
) -> Option<&'a [String]> {
let (path, symbol) = entry.anchor.rsplit_once('#')?;
if symbol.parse::<u32>().is_ok() {
return None;
}
symbols
.by_name
.get(symbol)?
.iter()
.filter_map(|identifier| symbols.records.get(*identifier))
.find(|record| {
record
.anchor
.rsplit_once('#')
.is_some_and(|(record_path, _)| record_path == path)
})
.map(|record| record.callers.as_slice())
.filter(|callers| !callers.is_empty())
}
fn trusted_route<'a>(
query: &str,
hits: &'a [(usize, crate::routes::RouteEntry)],
) -> Option<(usize, &'a crate::routes::RouteEntry, bool)> {
let (score, entry) = hits.first()?;
let words = crate::routes::normalize(query);
let unique_best = hits.get(1).is_none_or(|next| next.0 < *score);
let package_entry =
entry.state == crate::routes::RouteState::Auto && asks_for_package_entry(&words);
let trusted = entry.state != crate::routes::RouteState::Stale
&& unique_best
&& (*score >= 2 || package_entry);
trusted.then_some((*score, entry, package_entry))
}
fn candidate_maps(hits: &[(usize, crate::routes::RouteEntry)]) -> Vec<String> {
let mut candidates = Vec::new();
for (_, candidate) in hits.iter().take(3) {
if !candidates.iter().any(|map| map == &candidate.map) {
candidates.push(candidate.map.clone());
if candidates.len() == 3 {
break;
}
}
}
candidates
}
fn asks_for_overview(words: &[String]) -> bool {
words.iter().any(|word| {
word.starts_with("subsystem")
|| word == "components"
|| word.starts_with("module")
|| word.starts_with("structure")
|| word.starts_with("overview")
|| word.starts_with("orient")
})
}
struct SymbolCandidate<'a> {
score: usize,
coverage: usize,
direct: bool,
record: &'a IndexedSymbol,
}
fn is_signature_noise(word: &str) -> bool {
matches!(
word,
"async"
| "class"
| "const"
| "def"
| "fn"
| "function"
| "impl"
| "interface"
| "let"
| "mut"
| "pub"
| "public"
| "self"
| "struct"
)
}
fn intent_bonus(query_words: &[String], record: &IndexedSymbol) -> usize {
if query_words.iter().any(|word| {
word.starts_with("bonus")
|| word.starts_with("intent")
|| word.starts_with("rank")
|| word.starts_with("scor")
}) {
return 0;
}
let explicit_persistence = query_words.iter().any(|word| {
word.starts_with("persist")
|| word.starts_with("sav")
|| word.starts_with("stor")
|| matches!(word.as_str(), "database" | "db" | "write")
});
let inserts_data = query_words.iter().any(|word| word.starts_with("insert"))
&& query_words.iter().any(|word| {
word.starts_with("item")
|| word.starts_with("order")
|| word.starts_with("record")
|| word.starts_with("row")
|| word.starts_with("table")
});
let persistence_query = explicit_persistence || inserts_data;
let persistence_call = record.calls.iter().any(|call| {
crate::routes::split_ident(call).iter().any(|word| {
word.starts_with("commit")
|| word.starts_with("execut")
|| word.starts_with("insert")
|| word.starts_with("persist")
|| word.starts_with("quer")
|| word.starts_with("sav")
|| word.starts_with("stor")
|| word.starts_with("transact")
|| matches!(word.as_str(), "upsert" | "write")
})
});
let markup_query = query_words.iter().any(|word| {
word.starts_with("form")
|| word.starts_with("head")
|| word.starts_with("input")
|| word.starts_with("markup")
|| word.starts_with("template")
|| word.starts_with("textarea")
});
let path = record
.anchor
.split_once('#')
.map_or(record.anchor.as_str(), |(path, _)| path);
usize::from(persistence_query && persistence_call) * 20
+ usize::from(markup_query && (path.ends_with(".html") || path.ends_with(".htm"))) * 20
}
fn auxiliary_path(anchor: &str) -> bool {
let (path, symbol) = anchor.split_once('#').unwrap_or((anchor, ""));
if symbol == "tests" || symbol.starts_with("test_") {
return true;
}
path.split('/').any(|component| {
matches!(
component,
"bench"
| "benches"
| "example"
| "examples"
| "fixture"
| "fixtures"
| "test"
| "tests"
) || component.starts_with("test_")
|| component.ends_with("_test.rs")
|| component.ends_with(".test.js")
|| component.ends_with(".test.ts")
})
}
fn executable_intent_bonus(query_words: &[String], record: &IndexedSymbol) -> usize {
let asks_for_declaration = query_words.iter().any(|word| {
word.starts_with("class")
|| word.starts_with("constant")
|| word.starts_with("enum")
|| word.starts_with("field")
|| word.starts_with("interface")
|| word.starts_with("module")
|| word.starts_with("struct")
|| word.starts_with("trait")
|| word == "type"
});
usize::from(record.executable != asks_for_declaration) * 4
}
fn visibility_bonus(query_words: &[String], record: &IndexedSymbol) -> usize {
let asks_for_public_api = query_words
.iter()
.any(|word| word.starts_with("entry") || word.starts_with("public") || word == "api");
usize::from(asks_for_public_api && record.public) * 4
}
fn auxiliary_path_bonus(query_words: &[String], anchor: &str) -> usize {
let asks_for_auxiliary = query_words.iter().any(|word| {
word.starts_with("bench")
|| word.starts_with("exampl")
|| word.starts_with("fixtur")
|| word.starts_with("test")
});
usize::from(asks_for_auxiliary == auxiliary_path(anchor)) * 48
}
fn routing_aliases(words: &[String]) -> Vec<&'static str> {
let has = |prefix: &str| words.iter().any(|word| word.starts_with(prefix));
let mut aliases = Vec::new();
if has("lowercas") || has("stopword") || has("dedup") {
aliases.push("normalize");
}
if has("signature") && (has("front") || has("misplac") || has("mov")) {
aliases.extend(["canonicalize", "order"]);
}
if has("closest") {
aliases.push("nearest");
}
if has("token") && has("limit") {
aliases.push("budget");
}
if has("replac") && (has("append") || has("idempot")) {
aliases.push("upsert");
}
if has("route") && (has("confiden") || has("fresh") || has("trust")) {
aliases.push("trusted");
}
if has("route") && has("writ") {
aliases.push("save");
}
if has("execut") && has("path") && (has("exist") || has("check")) {
aliases.push("which");
}
if has("director") {
aliases.push("dir");
}
if has("escap") {
aliases.push("esc");
}
if has("relativ") {
aliases.push("rel");
}
if has("uri") {
aliases.push("uri");
}
aliases
}
fn routing_query_words(query: &str) -> Vec<String> {
let mut words = crate::routes::normalize(query);
words.extend(routing_aliases(&words).into_iter().map(str::to_string));
let mut seen_fingerprints = BTreeSet::new();
words.retain(|word| {
crate::routes::term_fingerprint(word)
.is_none_or(|fingerprint| seen_fingerprints.insert(fingerprint))
});
words
}
fn symbol_candidates<'a>(query: &str, symbols: &'a SymbolIndex) -> Vec<SymbolCandidate<'a>> {
let query_words = routing_query_words(query);
struct QueryTerm<'a> {
word: &'a str,
weight: usize,
fingerprint: Option<u32>,
}
let query_terms: Vec<QueryTerm<'_>> = query_words
.iter()
.map(|word| QueryTerm {
word,
weight: symbols.rarity(word),
fingerprint: crate::routes::term_fingerprint(word),
})
.collect();
let mut candidates = Vec::new();
for identifier in symbols.candidate_ids(&query_words) {
let record = &symbols.records[identifier];
let name = record
.anchor
.rsplit_once('#')
.map_or(record.anchor.as_str(), |(_, name)| name);
let name_words = crate::routes::split_ident(name);
let exact_name = if name_words.len() >= 2 {
let lower_name = name.to_lowercase();
query_terms.iter().any(|term| term.word == lower_name)
} else {
false
};
let mut name_hits = Vec::with_capacity(query_terms.len());
let mut body_contains = Vec::with_capacity(query_terms.len());
let mut name_matches = 0usize;
let mut name_weight = 0usize;
let mut body_matches = 0usize;
let mut body_weight = 0usize;
for term in &query_terms {
let name_hit = name_words
.iter()
.any(|name_word| crate::routes::tokens_match(term.word, name_word.as_str()));
let body_hit = term
.fingerprint
.is_some_and(|fingerprint| record.body_terms.binary_search(&fingerprint).is_ok());
if name_hit {
name_matches += 1;
name_weight += term.weight;
} else if body_hit {
body_matches += 1;
body_weight += term.weight;
}
name_hits.push(name_hit);
body_contains.push(body_hit);
}
if name_matches == 0 && !exact_name && body_matches < 2 {
continue;
}
let signature_words = crate::routes::normalize(&record.signature);
let call_words: Vec<String> = record
.calls
.iter()
.flat_map(|call| crate::routes::split_ident(call))
.collect();
let path_words: Vec<String> = record
.anchor
.split_once('#')
.map_or(record.anchor.as_str(), |(path, _)| path)
.split('/')
.flat_map(crate::routes::split_ident)
.collect();
let mut signature_hits = Vec::with_capacity(query_terms.len());
let mut detail_matches = 0usize;
let mut detail_weight = 0usize;
for (index, term) in query_terms.iter().enumerate() {
let signature_hit = signature_words.iter().any(|signature_word| {
crate::routes::tokens_match(term.word, signature_word.as_str())
});
let detail_hit = !name_hits[index]
&& signature_words.iter().any(|signature_word| {
!is_signature_noise(signature_word)
&& crate::routes::tokens_match(term.word, signature_word.as_str())
});
if detail_hit {
detail_matches += 1;
detail_weight += term.weight;
}
signature_hits.push(signature_hit);
}
let mut call_matches = 0usize;
let mut call_weight = 0usize;
let mut path_matches = 0usize;
let mut path_weight = 0usize;
for (index, term) in query_terms.iter().enumerate() {
if !name_hits[index]
&& !signature_hits[index]
&& !body_contains[index]
&& call_words
.iter()
.any(|call_word| crate::routes::tokens_match(term.word, call_word.as_str()))
{
call_matches += 1;
call_weight += term.weight;
}
if path_words
.iter()
.any(|path_word| crate::routes::tokens_match(term.word, path_word.as_str()))
{
path_matches += 1;
path_weight += term.weight;
}
}
let coverage = name_matches + detail_matches + body_matches + call_matches + path_matches;
let bonuses = [
visibility_bonus(&query_words, record),
executable_intent_bonus(&query_words, record),
auxiliary_path_bonus(&query_words, &record.anchor),
intent_bonus(&query_words, record),
];
candidates.push(SymbolCandidate {
score: usize::from(exact_name) * 100
+ name_weight * 5
+ detail_weight * 2
+ body_weight
+ call_weight
+ path_weight * 8
+ bonuses.iter().sum::<usize>(),
coverage: if exact_name {
2.max(coverage)
} else {
coverage
},
direct: exact_name || name_matches > 0 || body_matches >= 3,
record,
});
}
candidates.sort_by(|left, right| {
right
.score
.cmp(&left.score)
.then_with(|| right.coverage.cmp(&left.coverage))
.then_with(|| left.record.anchor.cmp(&right.record.anchor))
});
candidates.truncate(3);
candidates
}
fn direct_source(record: &IndexedSymbol, include_callers: bool) -> String {
let mut result = format!("FINAL SOURCE ANCHOR (copy exactly): {}", record.anchor);
if include_callers && !record.callers.is_empty() {
result.push_str("\ncallers: ");
result.push_str(&record.callers.join(", "));
}
result
}
fn render_symbol_candidates(candidates: &[SymbolCandidate<'_>]) -> String {
let mut result = String::from("source candidates:\n");
for candidate in candidates {
result.push_str(&candidate.record.anchor);
result.push('\n');
}
result
}
fn navigate_result(
root: &Path,
query: &str,
hits: &[(usize, crate::routes::RouteEntry)],
symbols: &SymbolIndex,
overview: &str,
) -> String {
let words = crate::routes::normalize(query);
if let Some((_, entry, _)) = trusted_route(query, hits) {
let mut result = format!("FINAL SOURCE ANCHOR (copy exactly): {}", entry.anchor);
if asks_for_callers(&words)
&& let Some(context) = direct_symbol_context(entry, symbols)
{
result.push_str("\ncallers: ");
result.push_str(&context.join(", "));
}
return result;
}
if asks_for_overview(&words) {
return overview.to_string();
}
let candidates = symbol_candidates(query, symbols);
if let Some(best) = candidates.first() {
const DIRECT_MARGIN: usize = 20;
let score_margin = candidates
.get(1)
.map_or(best.score, |next| best.score.saturating_sub(next.score));
if best.coverage >= 2 && best.direct && score_margin >= DIRECT_MARGIN {
return direct_source(best.record, asks_for_callers(&words));
}
return render_symbol_candidates(&candidates);
}
let mut maps = candidate_maps(hits);
if maps.is_empty() {
maps.push("MAP.md".to_string());
}
let metadata = read_map_metadata(&root.join(&maps[0]))
.unwrap_or_else(|_| "metadata unavailable\n".to_string());
format!("candidate maps: {}\n{metadata}", maps.join(", "))
}
fn file_stamp(path: &Path) -> Option<StateStamp> {
let metadata = std::fs::metadata(path).ok()?;
let modified_nanos = metadata
.modified()
.ok()?
.duration_since(UNIX_EPOCH)
.ok()?
.as_nanos();
Some(StateStamp {
bytes: metadata.len(),
modified_nanos,
})
}
struct ServerState {
root: PathBuf,
stamp: Option<StateStamp>,
routes_stamp: Option<StateStamp>,
routes: Vec<crate::routes::RouteEntry>,
symbols: SymbolIndex,
overview: String,
answers: HashMap<String, String>,
}
impl ServerState {
fn load(root: PathBuf) -> Self {
let (symbols, overview) = load_query_snapshot(&root).map_or_else(
|| {
let cache = crate::cache::ScanCache::load(&root);
(Self::index_symbols(&cache), Self::overview(&cache))
},
|snapshot| (snapshot.symbols, snapshot.overview),
);
let state_path = crate::cache::radar_dir(&root).join("state.bin");
let routes_path = crate::cache::radar_dir(&root).join("ROUTES.md");
let stamp = file_stamp(&state_path);
let routes_stamp = file_stamp(&routes_path);
let routes = crate::routes::load(&root);
Self {
root,
stamp,
routes_stamp,
routes,
symbols,
overview,
answers: HashMap::new(),
}
}
fn index_symbols(cache: &crate::cache::ScanCache) -> SymbolIndex {
const CALLER_LIMIT: usize = 3;
let mut callers: BTreeMap<&str, BTreeMap<&str, u32>> = BTreeMap::new();
for (rel, entry) in &cache.files {
let Some(lang) = entry.lang else { continue };
let Some(extraction) = cache.parses.get(&(lang, entry.hash)) else {
continue;
};
for reference in &extraction.refs {
if reference.kind == crate::extract::RefKind::Call {
callers
.entry(&reference.name)
.or_default()
.entry(rel)
.and_modify(|line| *line = (*line).min(reference.line))
.or_insert(reference.line);
}
}
}
let mut symbols = SymbolIndex::default();
for (rel, entry) in &cache.files {
let Some(lang) = entry.lang else { continue };
let Some(extraction) = cache.parses.get(&(lang, entry.hash)) else {
continue;
};
for definition in &extraction.defs {
let matching_callers: Vec<String> = callers
.get(definition.name.as_str())
.into_iter()
.flat_map(|paths| paths.iter())
.filter(|(path, _)| **path != rel.as_str())
.take(CALLER_LIMIT)
.map(|(path, line)| format!("{path}#{line}"))
.collect();
let calls: Vec<String> = extraction
.refs
.iter()
.filter(|reference| {
reference.kind == crate::extract::RefKind::Call
&& reference.line >= definition.line
&& reference.line <= definition.end_line
})
.map(|reference| reference.name.clone())
.collect::<BTreeSet<_>>()
.into_iter()
.take(16)
.collect();
symbols.insert(
definition.name.clone(),
IndexedSymbol {
anchor: format!("{rel}#{}", definition.name),
signature: definition.sig.clone(),
public: definition.vis == crate::extract::Vis::Pub,
executable: matches!(
definition.kind,
crate::extract::SymKind::Fn | crate::extract::SymKind::Method
),
body_terms: definition.terms.clone(),
callers: matching_callers,
calls,
},
);
}
}
symbols
}
fn overview(cache: &crate::cache::ScanCache) -> String {
let mut scopes: BTreeMap<String, OverviewScope> = BTreeMap::new();
for (relative, entry) in &cache.files {
let Some(lang) = entry.lang else { continue };
let (scope, local) = relative
.split_once('/')
.map_or((".", relative.as_str()), |(scope, local)| (scope, local));
let group = scopes.entry(scope.to_string()).or_default();
group.files.insert(local.to_string());
group.topics.extend(path_topics(local));
if let Some(extraction) = cache.parses.get(&(lang, entry.hash)) {
group.symbols.extend(
extraction
.defs
.iter()
.filter(|definition| definition.vis == crate::extract::Vis::Pub)
.map(|definition| definition.name.clone()),
);
}
}
let mut ranked: Vec<_> = scopes.into_iter().collect();
ranked.sort_by(|left, right| {
right
.1
.files
.len()
.cmp(&left.1.files.len())
.then_with(|| left.0.cmp(&right.0))
});
let mut result = String::from("FINAL REPOSITORY OVERVIEW:\n");
for (scope, group) in ranked.into_iter().take(3) {
let label = if scope == "." {
"root".to_string()
} else {
format!("{scope}/")
};
let evidence: Vec<_> = if group.topics.is_empty() {
group.symbols.iter().take(6).cloned().collect()
} else {
group.topics.iter().take(8).cloned().collect()
};
result.push_str(&format!(
"- {label}: {} ({} files)\n",
evidence.join(", "),
group.files.len(),
));
}
result
}
fn refresh_if_changed(&mut self) {
let state_path = crate::cache::radar_dir(&self.root).join("state.bin");
if file_stamp(&state_path) != self.stamp {
*self = Self::load(self.root.clone());
return;
}
let routes_path = crate::cache::radar_dir(&self.root).join("ROUTES.md");
if file_stamp(&routes_path) != self.routes_stamp {
self.reload_routes();
}
}
fn reload_routes(&mut self) {
self.routes = crate::routes::load(&self.root);
self.routes_stamp = file_stamp(&crate::cache::radar_dir(&self.root).join("ROUTES.md"));
self.answers.clear();
}
}
fn query_cache_key(query: &str) -> String {
crate::routes::normalize(query).join(" ")
}
fn source_packet(root: &Path, answer: &str, source: &SourceSnapshot) -> String {
const FINAL_PREFIX: &str = "FINAL SOURCE ANCHOR (copy exactly): ";
let Some(anchor) = answer
.lines()
.next()
.and_then(|line| line.strip_prefix(FINAL_PREFIX))
else {
return answer.to_string();
};
let Some((anchor_path, anchor_symbol)) = anchor.rsplit_once('#') else {
return format!(
"SOURCE UNAVAILABLE (no content returned): exact definition span is not indexed\n{FINAL_PREFIX}{anchor}"
);
};
let mut matching_spans = source.spans.iter().filter(|span| {
span.symbol == anchor_symbol
&& source
.files
.get(span.file as usize)
.is_some_and(|file| file.path == anchor_path)
});
let Some(span) = matching_spans.next() else {
return "SOURCE UNAVAILABLE (no content returned): definition span is missing; run `radar refresh`".to_string();
};
if matching_spans.next().is_some() {
return "SOURCE UNAVAILABLE (no content returned): definition anchor is ambiguous"
.to_string();
}
let Some(file) = source.files.get(span.file as usize) else {
return "SOURCE UNAVAILABLE (no content returned): source file is missing from the index; run `radar refresh`".to_string();
};
let lexical_path_is_safe = !file.path.is_empty()
&& Path::new(&file.path)
.components()
.all(|component| matches!(component, Component::Normal(_)));
let anchor_path = anchor.rsplit_once('#').map(|(path, _)| path);
if !lexical_path_is_safe || anchor_path != Some(file.path.as_str()) {
return "SOURCE UNAVAILABLE (no content returned): indexed path failed containment validation".to_string();
}
let Ok(canonical_root) = std::fs::canonicalize(root) else {
return "SOURCE UNAVAILABLE (no content returned): repository root is unreadable"
.to_string();
};
let source_path = root.join(&file.path);
let Ok(canonical_source) = std::fs::canonicalize(&source_path) else {
return format!(
"STALE SOURCE (no content returned): {} is unreadable; run `radar refresh`",
file.path
);
};
if !canonical_source.starts_with(&canonical_root) {
return "SOURCE UNAVAILABLE (no content returned): indexed path escapes repository root"
.to_string();
}
let Ok(metadata) = std::fs::symlink_metadata(&source_path) else {
return format!(
"STALE SOURCE (no content returned): {} is unreadable; run `radar refresh`",
file.path
);
};
if metadata.file_type().is_symlink() {
return "SOURCE UNAVAILABLE (no content returned): indexed source path is a symlink"
.to_string();
}
let Ok(bytes) = std::fs::read(&canonical_source) else {
return format!(
"STALE SOURCE (no content returned): {} is unreadable; run `radar refresh`",
file.path
);
};
if blake3::hash(&bytes).as_bytes() != &file.hash {
return format!(
"STALE SOURCE (no content returned): {} changed since indexing; run `radar refresh`",
file.path
);
}
let text = String::from_utf8_lossy(&bytes);
let definition: String = text
.split_inclusive('\n')
.skip(span.line.saturating_sub(1) as usize)
.take(span.end_line.saturating_sub(span.line) as usize + 1)
.collect();
if definition.is_empty() {
return format!(
"SOURCE UNAVAILABLE (no content returned): {}:{}-{} is outside the current file; run `radar refresh`",
file.path, span.line, span.end_line
);
}
let base = format!(
"{FINAL_PREFIX}{anchor}\nSOURCE SPAN (verified): {}:{}-{}\n",
file.path, span.line, span.end_line
);
const STATUS_RESERVE: usize = 64;
if base.len().saturating_add(STATUS_RESERVE) > MAX_SOURCE_PACKET_BYTES {
return "SOURCE UNAVAILABLE (no content returned): source metadata exceeds packet limit"
.to_string();
}
let available = MAX_SOURCE_PACKET_BYTES.saturating_sub(base.len() + STATUS_RESERVE);
let mut kept = definition.len().min(available);
while kept > 0 && !definition.is_char_boundary(kept) {
kept -= 1;
}
let omitted = definition.len().saturating_sub(kept);
let status = if omitted == 0 {
"SOURCE COMPLETE\n---\n".to_string()
} else {
format!("SOURCE TRUNCATED: {omitted} bytes omitted\n---\n")
};
let mut packet = String::with_capacity(base.len() + status.len() + kept);
packet.push_str(&base);
packet.push_str(&status);
packet.push_str(&definition[..kept]);
packet
}
fn call_tool(state: &mut ServerState, name: &str, args: &Value) -> Value {
state.refresh_if_changed();
match name {
"navigate" => {
let query = args["query"].as_str().unwrap_or_default();
let key = query_cache_key(query);
if let Some(answer) = state.answers.get(&key) {
return text_result(answer.clone());
}
let hits = crate::routes::find_in(&state.routes, query);
let answer =
navigate_result(&state.root, query, &hits, &state.symbols, &state.overview);
const ANSWER_CACHE_CAP: usize = 256;
if !answer.starts_with("candidate maps:") {
if state.answers.len() >= ANSWER_CACHE_CAP {
state.answers.clear();
}
state.answers.insert(key, answer.clone());
}
text_result(answer)
}
other => json!({
"content": [{ "type": "text", "text": format!("unknown tool {other:?}") }],
"isError": true
}),
}
}
pub fn query(root: &Path, task: &str) -> String {
let routes = crate::routes::load(root);
let hits = crate::routes::find_in(&routes, task);
if let Some((_, entry, _)) = trusted_route(task, &hits)
&& !asks_for_callers(&crate::routes::normalize(task))
{
return format!("FINAL SOURCE ANCHOR (copy exactly): {}", entry.anchor);
}
let state = ServerState::load(root.to_path_buf());
navigate_result(root, task, &hits, &state.symbols, &state.overview)
}
pub fn query_source(root: &Path, task: &str) -> String {
let source = load_source_snapshot(root).unwrap_or_else(|| {
let cache = crate::cache::ScanCache::load(root);
let source = SourceSnapshot::from_cache(
&cache,
file_stamp(&crate::cache::radar_dir(root).join("state.bin")),
);
let _ = save_source_snapshot(root, &source);
source
});
if let Some(span) = source.exact_task_span(task)
&& let Some(file) = source.files.get(span.file as usize)
{
let answer = format!(
"FINAL SOURCE ANCHOR (copy exactly): {}#{}",
file.path, span.symbol
);
return source_packet(root, &answer, &source);
}
source_packet(root, &query(root, task), &source)
}
pub fn serve(root: &Path) -> std::io::Result<()> {
let mut state = ServerState::load(root.to_path_buf());
let stdin = std::io::stdin();
let mut reader = BufReader::new(stdin.lock());
let stdout = std::io::stdout();
loop {
let Some((msg, framing)) = read_message(&mut reader)? else {
return Ok(());
};
let id = msg.get("id").cloned();
let method = msg.get("method").and_then(|m| m.as_str()).unwrap_or("");
let result = match method {
"initialize" => json!({
"protocolVersion": PROTOCOL,
"capabilities": { "tools": {} },
"serverInfo": { "name": "radar", "version": crate::VERSION }
}),
"tools/list" => json!({ "tools": tools() }),
"tools/call" => {
let name = msg["params"]["name"].as_str().unwrap_or("");
let args = &msg["params"]["arguments"];
call_tool(&mut state, name, args)
}
"ping" => json!({}),
_ => {
if id.is_none() {
continue;
}
json!({})
}
};
let Some(id) = id else { continue };
let response = json!({
"jsonrpc": "2.0", "id": id, "result": result
});
let mut out = stdout.lock();
write_message(&mut out, &response, framing)?;
}
}
#[cfg(test)]
mod tests {
use std::collections::{BTreeMap, HashMap};
use std::fs;
use std::io::Cursor;
use std::path::Path;
use super::{
IndexedSymbol, QuerySnapshot, SymbolIndex, intent_bonus, load_query_snapshot,
load_source_snapshot, map_metadata_head, navigate_result, query, query_cache_key,
query_snapshot_path, query_source, read_message, routing_query_words, save_query_snapshot,
source_packet, source_snapshot_path, tools,
};
use crate::routes::{RouteEntry, RouteState};
fn body_terms(words: &[&str]) -> Vec<u32> {
let mut terms: Vec<u32> = words
.iter()
.filter_map(|word| crate::routes::term_fingerprint(word))
.collect();
terms.sort_unstable();
terms.dedup();
terms
}
#[test]
fn advertised_surface_is_one_read_only_router() {
let listed = tools();
let listed = listed.as_array().expect("tool array");
assert_eq!(listed.len(), 1);
assert_eq!(listed[0]["name"], "navigate");
}
#[test]
fn query_snapshot_round_trips_and_corruption_is_a_cache_miss() {
let root =
std::env::temp_dir().join(format!("radar-query-snapshot-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&root);
std::fs::create_dir_all(&root).expect("mkdir");
save_query_snapshot(&root, &crate::cache::ScanCache::default()).expect("save snapshot");
let snapshot = load_query_snapshot(&root).expect("load snapshot");
assert!(snapshot.symbols.records.is_empty());
assert!(snapshot.overview.starts_with("FINAL REPOSITORY OVERVIEW:"));
assert!(load_source_snapshot(&root).is_some());
std::fs::write(query_snapshot_path(&root), b"corrupt").expect("corrupt snapshot");
assert!(load_query_snapshot(&root).is_none());
let mut source_bytes = std::fs::read(source_snapshot_path(&root)).expect("source bytes");
let last = source_bytes.last_mut().expect("source payload");
*last ^= 1;
std::fs::write(source_snapshot_path(&root), source_bytes).expect("corrupt source snapshot");
assert!(load_source_snapshot(&root).is_none());
let _ = std::fs::remove_dir_all(&root);
}
fn source_repo(tag: &str, body: &str) -> std::path::PathBuf {
let root =
std::env::temp_dir().join(format!("radar-source-packet-{tag}-{}", std::process::id()));
let _ = fs::remove_dir_all(&root);
fs::create_dir_all(&root).expect("mkdir");
fs::write(root.join("payment.py"), body).expect("write source");
crate::scan::scan(&crate::scan::ScanOpts {
root: root.clone(),
jobs: Some(1),
quiet: true,
})
.expect("scan source repository");
root
}
fn copy_tree(source: &Path, destination: &Path) {
fs::create_dir_all(destination).expect("create fixture directory");
for entry in fs::read_dir(source).expect("read fixture directory") {
let entry = entry.expect("fixture entry");
let target = destination.join(entry.file_name());
if entry.file_type().expect("fixture type").is_dir() {
copy_tree(&entry.path(), &target);
} else {
fs::copy(entry.path(), target).expect("copy fixture");
}
}
}
#[test]
fn source_query_returns_only_the_verified_definition_and_refuses_stale_content() {
let body = "def helper():\n return 'outside'\n\n\n@requires_auth\ndef settle_batch(batch_id, ledger):\n total = sum(ledger.entries(batch_id))\n return ledger.write_receipt(batch_id, total)\n";
let root = source_repo("verified", body);
let task = "Where is settle_batch defined?";
let packet = query_source(&root, task);
assert!(
packet.starts_with(
"FINAL SOURCE ANCHOR (copy exactly): payment.py#settle_batch\nSOURCE SPAN (verified): payment.py:5-8"
),
"{packet}"
);
assert!(packet.contains("def settle_batch"), "{packet}");
assert!(packet.contains("@requires_auth"), "{packet}");
assert!(
!packet.contains("outside"),
"neighbor leaked into packet: {packet}"
);
assert!(packet.len() <= super::MAX_SOURCE_PACKET_BYTES);
fs::write(query_snapshot_path(&root), b"corrupt").expect("corrupt general query snapshot");
fs::write(source_snapshot_path(&root), b"corrupt").expect("corrupt source snapshot");
assert_eq!(query_source(&root, task), packet);
assert!(
load_source_snapshot(&root).is_some(),
"source snapshot self-heals"
);
fs::write(root.join("payment.py"), format!("{body}\n# changed\n")).expect("change source");
let stale = query_source(&root, task);
assert!(
stale.starts_with("STALE SOURCE (no content returned):"),
"{stale}"
);
assert!(!stale.contains("def settle_batch"), "{stale}");
let _ = fs::remove_dir_all(root);
}
#[test]
fn source_query_caps_large_definitions_and_keeps_weak_results_as_candidates() {
let mut body = String::from("def settle_batch(batch_id):\n");
for index in 0..2000 {
body.push_str(&format!(" value_{index} = {index}\n"));
}
body.push_str(" return batch_id\n");
let root = source_repo("bounded", &body);
let packet = query_source(&root, "Where is settle_batch defined?");
assert!(packet.contains("SOURCE TRUNCATED:"), "{packet}");
assert!(packet.len() <= super::MAX_SOURCE_PACKET_BYTES);
fs::write(
root.join("other.py"),
"def settle_batch(batch_id):\n return batch_id\n",
)
.expect("write ambiguity");
crate::scan::scan(&crate::scan::ScanOpts {
root: root.clone(),
jobs: Some(1),
quiet: true,
})
.expect("rescan ambiguous repository");
let candidates = query_source(&root, "Where is settle_batch defined?");
assert!(candidates.starts_with("source candidates:"), "{candidates}");
assert!(!candidates.contains("SOURCE SPAN"), "{candidates}");
let _ = fs::remove_dir_all(root);
}
#[test]
fn source_packets_cover_every_supported_parser_mode() {
let root = std::env::temp_dir().join(format!(
"radar-source-packet-languages-{}",
std::process::id()
));
let _ = fs::remove_dir_all(&root);
copy_tree(
&Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/corpus/valid"),
&root,
);
fs::write(root.join("sfdx-project.json"), "{}\n").expect("Salesforce marker");
let (_, cache) = crate::scan::scan_full(&crate::scan::ScanOpts {
root: root.clone(),
jobs: Some(1),
quiet: true,
})
.expect("scan language corpus");
for language in crate::lang::Lang::ALL {
let (relative, definition) = cache
.files
.iter()
.find_map(|(relative, entry)| {
(entry.lang == Some(language)).then(|| {
cache
.parses
.get(&(language, entry.hash))
.and_then(|extraction| {
extraction.defs.iter().find(|candidate| {
extraction
.defs
.iter()
.filter(|definition| definition.name == candidate.name)
.count()
== 1
})
})
.map(|definition| (relative.clone(), definition.clone()))
})?
})
.unwrap_or_else(|| panic!("missing indexed definition for {}", language.name()));
let isolated = root.join(format!("isolated-{}", language.name()));
fs::create_dir_all(&isolated).expect("create isolated fixture root");
let filename = Path::new(&relative).file_name().expect("fixture filename");
let isolated_source = isolated.join(filename);
fs::copy(root.join(&relative), &isolated_source).expect("copy isolated fixture");
if language == crate::lang::Lang::Apex {
fs::write(isolated.join("sfdx-project.json"), "{}\n").expect("Salesforce marker");
}
crate::scan::scan(&crate::scan::ScanOpts {
root: isolated.clone(),
jobs: Some(1),
quiet: true,
})
.expect("scan isolated language fixture");
let packet = query_source(
&isolated,
&format!(
"In {}, return its complete implementation.",
definition.name
),
);
let path = filename.to_string_lossy();
let expected_header = format!(
"FINAL SOURCE ANCHOR (copy exactly): {path}#{}\nSOURCE SPAN (verified): {path}:{}-{}\nSOURCE COMPLETE\n---\n",
definition.name, definition.line, definition.end_line
);
assert!(
packet.starts_with(&expected_header),
"{}: {packet}",
language.name()
);
let text = fs::read_to_string(&isolated_source).expect("read isolated fixture");
let expected_body: String = text
.split_inclusive('\n')
.skip(definition.line.saturating_sub(1) as usize)
.take(definition.end_line.saturating_sub(definition.line) as usize + 1)
.collect();
assert_eq!(
packet.strip_prefix(&expected_header),
Some(expected_body.as_str()),
"{} returned a different source range",
language.name()
);
assert!(packet.len() <= super::MAX_SOURCE_PACKET_BYTES);
}
let _ = fs::remove_dir_all(root);
}
#[test]
fn source_packet_rejects_duplicate_same_file_anchors() {
let body =
"def duplicate():\n return 'first'\n\ndef duplicate():\n return 'second'\n";
let root = source_repo("duplicate-anchor", body);
let source = load_source_snapshot(&root).expect("source snapshot");
let packet = source_packet(
&root,
"FINAL SOURCE ANCHOR (copy exactly): payment.py#duplicate",
&source,
);
assert!(packet.contains("anchor is ambiguous"), "{packet}");
assert!(!packet.contains("return 'first'"), "{packet}");
assert!(!packet.contains("return 'second'"), "{packet}");
let _ = fs::remove_dir_all(root);
}
#[cfg(unix)]
#[test]
fn source_packet_rejects_symlink_escape() {
use std::os::unix::fs::symlink;
let root =
std::env::temp_dir().join(format!("radar-source-symlink-root-{}", std::process::id()));
let outside = std::env::temp_dir().join(format!(
"radar-source-symlink-outside-{}.py",
std::process::id()
));
let _ = fs::remove_dir_all(&root);
let _ = fs::remove_file(&outside);
fs::create_dir_all(&root).expect("create root");
let body = "def leak():\n return 'outside'\n";
fs::write(&outside, body).expect("write outside source");
symlink(&outside, root.join("leak.py")).expect("create symlink");
let source = super::SourceSnapshot {
state_stamp: None,
files: vec![super::IndexedSourceFile {
path: "leak.py".into(),
hash: *blake3::hash(body.as_bytes()).as_bytes(),
}],
spans: vec![super::IndexedSourceSpan {
file: 0,
line: 1,
end_line: 2,
symbol: "leak".into(),
}],
};
let packet = source_packet(
&root,
"FINAL SOURCE ANCHOR (copy exactly): leak.py#leak",
&source,
);
assert!(packet.contains("escapes repository root"), "{packet}");
assert!(!packet.contains("return 'outside'"), "{packet}");
let _ = fs::remove_dir_all(root);
let _ = fs::remove_file(outside);
}
#[test]
fn query_snapshot_rejects_newer_state_and_invalid_postings() {
let root = std::env::temp_dir().join(format!(
"radar-query-snapshot-provenance-{}",
std::process::id()
));
let _ = fs::remove_dir_all(&root);
fs::create_dir_all(&root).expect("mkdir");
let mut cache = crate::cache::ScanCache::default();
cache.save(&root).expect("save state");
save_query_snapshot(&root, &cache).expect("save snapshot");
assert!(load_query_snapshot(&root).is_some(), "matching state loads");
cache.notices.no_git = true;
cache.files.insert(
"new.bin".into(),
crate::cache::FileEntry {
mtime: (2, 0),
size: 123,
ino: 0,
hash: [7; 32],
lang: None,
},
);
cache.save(&root).expect("rewrite state");
assert!(
load_query_snapshot(&root).is_none(),
"newer canonical state invalidates the old snapshot"
);
let snapshot = QuerySnapshot {
state_stamp: super::file_stamp(&crate::cache::radar_dir(&root).join("state.bin")),
symbols: SymbolIndex {
records: Vec::new(),
by_name: BTreeMap::new(),
postings: HashMap::from([(123, vec![0])]),
},
overview: "overview".into(),
};
let payload = postcard::to_stdvec(&snapshot).expect("encode invalid snapshot");
let mut bytes = b"RDARQ2\n".to_vec();
bytes.extend_from_slice(&payload);
fs::write(query_snapshot_path(&root), bytes).expect("write invalid snapshot");
assert!(
load_query_snapshot(&root).is_none(),
"out-of-range posting IDs are rejected before query routing"
);
let _ = fs::remove_dir_all(&root);
}
#[test]
fn oversized_content_length_is_rejected_before_body_allocation() {
let mut input = Cursor::new(b"Content-Length: 16777217\r\n\r\n".to_vec());
let error = read_message(&mut input).expect_err("oversized frame must fail");
assert_eq!(error.kind(), std::io::ErrorKind::InvalidData);
}
#[test]
fn exact_query_cache_key_ignores_case_and_repeated_whitespace() {
assert_eq!(query_cache_key(" Where Is SETTLEMENT? "), "settlement");
}
#[test]
fn query_cache_key_collapses_non_semantic_route_wrappers() {
assert_eq!(
query_cache_key("Can you please tell me about payment batch settlement?"),
query_cache_key("payment batch settlement")
);
assert_ne!(
query_cache_key("which file calls verify token"),
query_cache_key("verify token")
);
}
#[test]
fn routing_words_expand_high_precision_code_concepts() {
let words = routing_query_words(
"Where is the closest directory anchor replaced and appended idempotently?",
);
for expected in ["nearest", "dir", "upsert"] {
assert!(words.iter().any(|word| word == expected), "{words:?}");
}
assert!(
routing_query_words("Where are token limits selected?")
.iter()
.any(|word| word == "budget")
);
let route_words =
routing_query_words("Where is a fresh route written after confidence checking?");
for expected in ["trusted", "save"] {
assert!(
route_words.iter().any(|word| word == expected),
"{route_words:?}"
);
}
}
#[test]
fn query_returns_a_trusted_route_without_loading_the_repository_index() {
let root = std::env::temp_dir().join(format!("radar-query-route-{}", std::process::id()));
let _ = fs::remove_dir_all(&root);
fs::create_dir_all(root.join(".radar")).expect("create radar directory");
fs::write(
root.join(".radar/ROUTES.md"),
"[ok] benchmark unique route | src/lib.rs#answer | src/MAP.md | deadbeef | 1 | 1\n",
)
.expect("write routes");
assert_eq!(
query(&root, "benchmark unique route"),
"FINAL SOURCE ANCHOR (copy exactly): src/lib.rs#answer"
);
fs::remove_dir_all(root).expect("remove temporary repository");
}
#[test]
fn metadata_reader_stops_before_the_map_body() {
let doc = "---\nmap: 1\nscope: src\nchildren: [api/MAP.md]\nfidelity: syntax\napi_hash: abc\nstamped: now\n---\n## API\nsecret body\n";
let metadata = map_metadata_head(&mut Cursor::new(doc)).expect("metadata");
assert!(metadata.contains("scope: src"), "{metadata}");
assert!(metadata.contains("children: [api/MAP.md]"), "{metadata}");
assert!(!metadata.contains("api_hash"), "{metadata}");
assert!(!metadata.contains("secret body"), "{metadata}");
}
#[test]
fn metadata_reader_bounds_wide_child_lists() {
let children = (0..500)
.map(|index| format!("package{index}/MAP.md"))
.collect::<Vec<_>>()
.join(", ");
let doc = format!("---\nmap: 1\nscope: .\nchildren: [{children}]\nfidelity: syntax\n---\n");
let metadata = map_metadata_head(&mut Cursor::new(doc)).expect("metadata");
assert!(metadata.contains("package5/MAP.md"), "{metadata}");
assert!(!metadata.contains("package6/MAP.md"), "{metadata}");
assert!(metadata.contains("children_omitted: 494"), "{metadata}");
assert!(
metadata.len() < 256,
"metadata preview grew to {} bytes",
metadata.len()
);
}
#[test]
fn caller_query_gets_context_only_after_a_trusted_route() {
let entry = RouteEntry {
state: RouteState::Auto,
keywords: vec!["verify".into(), "token".into()],
anchor: "api/tokens.py#verify_token".into(),
map: "api/MAP.md".into(),
token: "abc".into(),
hits: 0,
seq: 1,
links: Vec::new(),
};
let hits = vec![(2, entry)];
let symbols = SymbolIndex::from_grouped(BTreeMap::from([(
"verify_token".into(),
vec![IndexedSymbol {
anchor: "api/tokens.py#verify_token".into(),
signature: "def verify_token(token)".into(),
public: true,
executable: true,
body_terms: Vec::new(),
callers: vec!["api/app.py#9".into()],
calls: Vec::new(),
}],
)]));
let trace = navigate_result(
Path::new("."),
"which file calls verify token",
&hits,
&symbols,
"overview",
);
assert_eq!(
trace,
"FINAL SOURCE ANCHOR (copy exactly): api/tokens.py#verify_token\ncallers: api/app.py#9"
);
let location = navigate_result(
Path::new("."),
"where is verify token",
&hits,
&symbols,
"overview",
);
assert_eq!(
location,
"FINAL SOURCE ANCHOR (copy exactly): api/tokens.py#verify_token"
);
}
#[test]
fn unique_two_word_symbol_match_is_direct() {
let symbols = SymbolIndex::from_grouped(BTreeMap::from([(
"settle_batch".into(),
vec![IndexedSymbol {
anchor: "payments/mod_07.py#settle_batch".into(),
signature: "def settle_batch(records)".into(),
public: true,
executable: true,
body_terms: Vec::new(),
callers: Vec::new(),
calls: vec!["commit".into()],
}],
)]));
let result = navigate_result(
Path::new("."),
"Where is payment batch settlement handled?",
&[],
&symbols,
"overview",
);
assert_eq!(
result,
"FINAL SOURCE ANCHOR (copy exactly): payments/mod_07.py#settle_batch"
);
}
#[test]
fn singular_component_locates_a_symbol_but_plural_requests_an_overview() {
let symbols = SymbolIndex::from_grouped(BTreeMap::from([(
"SecretCard".into(),
vec![IndexedSymbol {
anchor: "src/components/SecretCard.jsx#SecretCard".into(),
signature: "function SecretCard()".into(),
public: true,
executable: true,
body_terms: Vec::new(),
callers: Vec::new(),
calls: Vec::new(),
}],
)]));
assert_eq!(
navigate_result(
Path::new("."),
"where is the React secret card component?",
&[],
&symbols,
"overview",
),
"FINAL SOURCE ANCHOR (copy exactly): src/components/SecretCard.jsx#SecretCard"
);
assert_eq!(
navigate_result(
Path::new("."),
"what components does this repository have?",
&[],
&symbols,
"overview",
),
"overview"
);
}
#[test]
fn markup_intent_bonus_targets_html_anchors() {
let mut record = IndexedSymbol {
anchor: "templates/dashboard.html#secret-dashboard".into(),
signature: "<main id=\"secret-dashboard\">".into(),
public: true,
executable: false,
body_terms: Vec::new(),
callers: Vec::new(),
calls: Vec::new(),
};
assert_eq!(intent_bonus(&["heading".into()], &record), 20);
record.anchor = "src/components/SecretCard.jsx#SecretCard".into();
assert_eq!(intent_bonus(&["heading".into()], &record), 0);
}
#[test]
fn source_body_and_path_evidence_beat_test_name_overlap() {
let symbols = SymbolIndex::from_grouped(BTreeMap::from([
(
"read_message".into(),
vec![IndexedSymbol {
anchor: "src/mcp.rs#read_message".into(),
signature: "fn read_message(reader: &mut impl BufRead)".into(),
public: false,
executable: true,
body_terms: body_terms(&["content", "length", "json", "newline"]),
callers: Vec::new(),
calls: vec!["read_line".into()],
}],
),
(
"mcp_accepts_standard_newline_framing".into(),
vec![IndexedSymbol {
anchor: "tests/mcp.rs#mcp_accepts_standard_newline_framing".into(),
signature: "fn mcp_accepts_standard_newline_framing()".into(),
public: false,
executable: true,
body_terms: body_terms(&["content", "length"]),
callers: Vec::new(),
calls: Vec::new(),
}],
),
]));
let result = navigate_result(
Path::new("."),
"where are Content-Length and newline JSON messages parsed for MCP?",
&[],
&symbols,
"overview",
);
assert_eq!(
result,
"FINAL SOURCE ANCHOR (copy exactly): src/mcp.rs#read_message"
);
}
#[test]
fn persistence_intent_breaks_an_ambiguous_symbol_tie() {
let symbols = SymbolIndex::from_grouped(BTreeMap::from([
(
"place_order".into(),
vec![IndexedSymbol {
anchor: "api/orders.py#place_order".into(),
signature: "def place_order(user, items)".into(),
public: true,
executable: true,
body_terms: Vec::new(),
callers: Vec::new(),
calls: vec!["execute".into()],
}],
),
(
"submitOrder".into(),
vec![IndexedSymbol {
anchor: "web/orders.ts#submitOrder".into(),
signature: "async function submitOrder(token, items)".into(),
public: true,
executable: true,
body_terms: Vec::new(),
callers: Vec::new(),
calls: vec!["fetch".into()],
}],
),
(
"Order".into(),
vec![IndexedSymbol {
anchor: "web/api.ts#Order".into(),
signature: "interface Order".into(),
public: true,
executable: false,
body_terms: Vec::new(),
callers: Vec::new(),
calls: Vec::new(),
}],
),
]));
let result = navigate_result(
Path::new("."),
"Which function inserts a new order and all items into storage?",
&[],
&symbols,
"overview",
);
assert_eq!(
result,
"FINAL SOURCE ANCHOR (copy exactly): api/orders.py#place_order"
);
let ambiguous = navigate_result(
Path::new("."),
"Which order function handles items?",
&[],
&symbols,
"overview",
);
assert!(ambiguous.starts_with("source candidates:"), "{ambiguous}");
assert!(
ambiguous.contains("api/orders.py#place_order"),
"{ambiguous}"
);
assert!(
ambiguous.contains("web/orders.ts#submitOrder"),
"{ambiguous}"
);
}
}