Exact-match files lose to semantic guesses in aft_search, with no topK that surfaces them.
Repro (project with jcode checked out under it, both indexes Ready: search 2K files, semantic 30K entries):
aft_search("not wired into the built-in browser tool yet", topK=5) — the string exists verbatim in crates/jcode-app-core/src/tool/browser.rs:348. The file is not in the results. Not ignored, not a test file.
aft_search("wired yet", topK=10) — both words sit in one sentence in that file. Still absent, amid unrelated auth/mermaid hits.
aft_search("wired browser", topK=100) — 100 results, the exact-match file never appears. A different file (jcode-base/src/browser.rs) ranks; the one containing the literal query does not.
- AFT's own
grep tool finds it first try: browser.rs:348.
Mechanism, from source:
crates/aft/src/commands/semantic_search.rs:choose_mode sends NL queries over 2 words to pure SearchMode::Semantic. The trigram lane never runs for case 1, even though it covers all project text files and would match the literal phrase.
- In
Hybrid (cases 2-3), fuse_hybrid_results appends lexical-only hits after every semantic hit, then truncates to topK. Semantic returns fill the budget, so the exact match is cut even at topK=100.
The quoted-phrase second chance (extract_lexical_tokens) does not cover this: it needs quotes or a zero-result escalation, and case 1 returns nonzero semantic results.
Suggested direction: run the trigram lane for long NL queries too, and rank files matching all lexical tokens above semantic-only guesses in fusion instead of appending them post-truncate. Happy to test a branch.
Environment: aft 0.54.x, remote NVIDIA embeddings (nemotron-3-embed-1b), project root containing the jcode tree.
Exact-match files lose to semantic guesses in aft_search, with no topK that surfaces them.
Repro (project with jcode checked out under it, both indexes Ready: search 2K files, semantic 30K entries):
aft_search("not wired into the built-in browser tool yet", topK=5)— the string exists verbatim incrates/jcode-app-core/src/tool/browser.rs:348. The file is not in the results. Not ignored, not a test file.aft_search("wired yet", topK=10)— both words sit in one sentence in that file. Still absent, amid unrelated auth/mermaid hits.aft_search("wired browser", topK=100)— 100 results, the exact-match file never appears. A different file (jcode-base/src/browser.rs) ranks; the one containing the literal query does not.greptool finds it first try:browser.rs:348.Mechanism, from source:
crates/aft/src/commands/semantic_search.rs:choose_modesends NL queries over 2 words to pureSearchMode::Semantic. The trigram lane never runs for case 1, even though it covers all project text files and would match the literal phrase.Hybrid(cases 2-3),fuse_hybrid_resultsappends lexical-only hits after every semantic hit, then truncates to topK. Semantic returns fill the budget, so the exact match is cut even at topK=100.The quoted-phrase second chance (
extract_lexical_tokens) does not cover this: it needs quotes or a zero-result escalation, and case 1 returns nonzero semantic results.Suggested direction: run the trigram lane for long NL queries too, and rank files matching all lexical tokens above semantic-only guesses in fusion instead of appending them post-truncate. Happy to test a branch.
Environment: aft 0.54.x, remote NVIDIA embeddings (nemotron-3-embed-1b), project root containing the jcode tree.