From 645d4101bf8c55b97e3286f4f1d41c5615c3c878 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Tue, 3 Nov 2026 02:21:55 -0800 Subject: [PATCH 1/2] fix(search): rank JSON object keys below code definitions JSON top-level object members are extracted as Const symbols to support configuration resolution, but they are data keys rather than executable definitions. Their name matches previously received the same privileged source-role tier as code declarations, crowding capped symbol pages. Keep JSON keys searchable, with their original lexical score, while reserving ProductionDefinition for actual non-JSON code definitions. Leave test-file precedence and exact/lexical authorization unchanged. Add role classification checks and a mixed JSON/Rust/test corpus regression through the real sealed lexical artifact. The bounded winner heap must select the code definition, and a configuration-scoped query must still retrieve the JSON key. Refs #4451: the larger multiword ranking and corpus acceptance is separate from this JSON-key source-role fix. --- .../src/retrieval/source_tier.rs | 21 +++- .../search_quality_suite/source_roles.rs | 100 ++++++++++++++++++ 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/crates/tracedecay-query/src/retrieval/source_tier.rs b/crates/tracedecay-query/src/retrieval/source_tier.rs index ada450aab0..ce8cc7943c 100644 --- a/crates/tracedecay-query/src/retrieval/source_tier.rs +++ b/crates/tracedecay-query/src/retrieval/source_tier.rs @@ -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 @@ -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 diff --git a/crates/tracedecay-query/tests/search_quality_suite/source_roles.rs b/crates/tracedecay-query/tests/search_quality_suite/source_roles.rs index 3372726a74..8124e892a4 100644 --- a/crates/tracedecay-query/tests/search_quality_suite/source_roles.rs +++ b/crates/tracedecay-query/tests/search_quality_suite/source_roles.rs @@ -212,3 +212,103 @@ 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") + })); +} From 610b82ca320c8a1134f614729c2dd34fd98d51da Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Tue, 3 Nov 2026 04:33:44 -0800 Subject: [PATCH 2/2] style(search): format JSON key ranking regression Apply the exact rustfmt change from the repository gate failure while retaining the test assertion and candidate-ranking behavior. --- .../tests/search_quality_suite/source_roles.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/tracedecay-query/tests/search_quality_suite/source_roles.rs b/crates/tracedecay-query/tests/search_quality_suite/source_roles.rs index 8124e892a4..6505217f00 100644 --- a/crates/tracedecay-query/tests/search_quality_suite/source_roles.rs +++ b/crates/tracedecay-query/tests/search_quality_suite/source_roles.rs @@ -270,7 +270,10 @@ fn json_object_keys_remain_searchable_but_do_not_outrank_code_definitions() { } } assert!(json_seen, "the JSON key must remain retrievable"); - assert!(code_definition_seen, "the Rust function must remain a definition"); + assert!( + code_definition_seen, + "the Rust function must remain a definition" + ); let first = results.candidates.first().expect("named code candidate"); assert_eq!(