feat: wildcard/relaxed query fallback when primary search returns zero results (F1.1) #29
Notifications
Due Date
No due date set.
Depends on
#5 feat: Implement Tantivy-based session index for full-text search
terraphim/agent-tasks
Reference: terraphim/agent-tasks#29
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem Statement
Spec F1.1 (terraphim-agent-session-search-spec.md, lines 482-509) defines the canonical robot-mode response with
meta.wildcard_fallback: bool. Issue #21 wires the meta field, but the underlying behaviour -- "fall back to a wildcard / relaxed query when the primary search returns zero hits" -- is not implemented. Without it, the field can never betrue, so the spec semantics are unobservable.Verification:
The user-facing failure mode today:
terraphim-agent --robot search "async DB pool exhaustion in tokio runtime"returns zero results when no document matches the full phrase, even though sessions exist for "async pool" and "tokio". Agents and humans alike must manually iterate, which violates G2 ("zero parse failures from typos") and degrades G1 (search latency on the perceived path; users effectively retry).Acceptance Criteria
crates/terraphim_service/src/search/fallback.rs(or extend the search module already in service) implementing:WildcardSuffix->DropLowestScoringTerm->ConceptExpansion; stop at the first strategy that produces >= 1 hitmeta.wildcard_fallback = Some(true)ANDmeta.fallback_strategy = Some("wildcard_suffix" | "drop_term" | "concept_expansion")is set on the response envelopemeta.wildcard_fallback = Some(false)andmeta.fallback_strategy = None--no-fallbackonsearchand/sessions searchto disable; documented inrobot/docs.rssorobot schemas searchshows itterraphim_service::search(document search path)terraphim_sessions::Sessionservice::search(session search path) -- depends on #5 Tantivy index landing first; until then, session-search fallback is a no-op stub returningFallbackOutcome::default()"async pool"->"async* pool*"; DropLowestScoringTerm picks the rarest token (use a fixture frequency table); ConceptExpansion uses a fixture thesaurusmeta.fallback_strategy == "wildcard_suffix"--no-fallback, assert zero results andmeta.wildcard_fallback == Some(false)even when fallbacks would have helpedcargo test -p terraphim_service search::fallbackpassescargo test -p terraphim_agent --features repl-full search_wildcard_fallbackpassescargo clippy -p terraphim_service -p terraphim_agent -- -D warningspassesProposed Approach
service.rs::searchruns primary first, then iterates strategies on zero-hitterraphim_automata::find_matchesagainst the active role thesaurus to expand each token to its top-3 synonyms; cap expanded query length to 32 tokens to avoid runawaymeta.fallback_strategy: Option<String>toResponseMeta(separate fromwildcard_fallback) so consumers can branch on which strategy ran -- see #21 for the meta-extension patternconcepts_matched+ the boolean): this issue closes the loop by emitting the strategy name AND makingwildcard_fallback = trueactually achievableDependencies
ResponseMetafurther; if this lands first, #21 just addsconcepts_matchedVerification
Expected first call:
meta.wildcard_fallback == trueANDfallback_strategyis one ofwildcard_suffix|drop_term|concept_expansion. Second call:false, no strategy.Scope
Single PR, ~400-500 LOC across
terraphim_service::search::fallback(~200), service orchestrator wiring (~60), session-service stub (~20), CLI/docs (~30), tests (~150). Closes the F1.1 spec semantic gap left by #21.Upstream: terraphim-agent-session-search-spec.md F1.1 (lines 482-509) -- complements #21.