Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions crates/tracedecay-query/src/retrieval/source_tier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ use tracedecay_domain::{CodeSearchChunkGrainV1, RetrievalSourceRoleV1};
use super::lexical::LexicalFieldV1;

/// Classify a hit from the existing test-path authority plus whether the
/// matched evidence is a name or signature definition.
/// matched evidence is a name or signature definition. JSON object keys are
/// searchable configuration data, not executable code definitions: treating
/// each key as a production definition fills capped symbol pages ahead of
/// real declarations. Keep the key eligible and its raw score unchanged.
pub(crate) fn classify_source_role(path: &str, definition_match: bool) -> RetrievalSourceRoleV1 {
if is_test_file(path) {
RetrievalSourceRoleV1::TestReference
} else if definition_match {
} else if definition_match && !path.ends_with(".json") {
RetrievalSourceRoleV1::ProductionDefinition
} else {
RetrievalSourceRoleV1::ProductionOther
Expand Down Expand Up @@ -85,6 +88,20 @@ mod tests {
classify_source_role("src/internal/client/ensure-daemon.test.ts", true),
RetrievalSourceRoleV1::TestReference
);
assert_eq!(
classify_source_role("config/render.json", true),
RetrievalSourceRoleV1::ProductionOther,
"a JSON key remains searchable but cannot preempt a code definition"
);
assert_eq!(
classify_source_role("config/render.json", false),
RetrievalSourceRoleV1::ProductionOther
);
assert_eq!(
classify_source_role("tests/render.json", true),
RetrievalSourceRoleV1::TestReference,
"test source retains its own lower-priority role"
);
assert_eq!(
RetrievalSourceRoleV1::ProductionDefinition.admission_rank(),
0
Expand Down
103 changes: 103 additions & 0 deletions crates/tracedecay-query/tests/search_quality_suite/source_roles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,106 @@ fn name_filtered_routes_keep_undocumented_symbol_hits() {
);
}
}

#[test]
fn json_object_keys_remain_searchable_but_do_not_outrank_code_definitions() {
// This fixture travels through the real JSON/Rust extractors, sealed
// lexical artifact, bounded winner heap and emitted source-role evidence.
// A JSON pair is extracted as a Const, but it is configuration data, not
// an executable definition of the same-named Rust function.
let fixture = real_lexical_source_fixture_from_sources(vec![
(
"file.json".to_owned(),
"config/render.json".to_owned(),
br#"{"render": true, "other": false}"#.to_vec(),
),
(
"file.code".to_owned(),
"src/render.rs".to_owned(),
b"pub fn render() -> bool { true }\n".to_vec(),
),
(
"file.test".to_owned(),
"tests/render.rs".to_owned(),
b"#[test] fn render() { assert!(true); }\n".to_vec(),
),
]);
let artifact = sealed_artifact(&fixture, fixture.metadata.clone());
let lane = LexicalLane::new(artifact.reader.clone());
let request = artifact.request("render", &["render"], &[], &[], 0, 32);
let results = complete(
lane.retrieve_lexical(&request)
.expect("sealed lexical search"),
);

let mut json_seen = false;
let mut code_definition_seen = false;
for candidate in &results.candidates {
let file = candidate
.file_occurrence_id
.as_ref()
.expect("file occurrence")
.as_str();
let role = results.evidence_by_occurrence[&candidate.source_occurrence_id].source_role;
match file {
"file.json" => {
json_seen = true;
assert_ne!(
role,
RetrievalSourceRoleV1::ProductionDefinition,
"JSON object keys must not take the code-definition tier"
);
}
"file.code" => {
code_definition_seen |= role == RetrievalSourceRoleV1::ProductionDefinition;
}
"file.test" => assert_eq!(role, RetrievalSourceRoleV1::TestReference),
other => panic!("unexpected fixture file {other}"),
}
}
assert!(json_seen, "the JSON key must remain retrievable");
assert!(
code_definition_seen,
"the Rust function must remain a definition"
);

let first = results.candidates.first().expect("named code candidate");
assert_eq!(
first.file_occurrence_id.as_ref().unwrap().as_str(),
"file.code",
"a production declaration outranks a same-named JSON object key"
);
let capped = artifact.request("render", &["render"], &[], &[], 0, 1);
let capped_results = complete(
lane.retrieve_lexical(&capped)
.expect("bounded lexical search"),
);
assert_eq!(capped_results.candidates.len(), 1);
assert_eq!(
capped_results.candidates[0]
.file_occurrence_id
.as_ref()
.unwrap()
.as_str(),
"file.code",
"capped admission must apply the same priority as emitted evidence"
);

// A user explicitly searching configuration still finds its actual keys.
let mut scoped = artifact.request("render", &["render"], &[], &[], 0, 32);
scoped.path_prefix = Some("config");
let scoped_results = complete(
lane.retrieve_lexical(&scoped)
.expect("configuration-scoped search"),
);
assert!(
!scoped_results.candidates.is_empty(),
"lower priority is not a filter or an opt-out"
);
assert!(scoped_results.candidates.iter().all(|candidate| {
candidate
.file_occurrence_id
.as_ref()
.is_some_and(|file| file.as_str() == "file.json")
}));
}
Loading