Compare commits

...
Author SHA1 Message Date
m 75a8533939 Reject distance sources without measured evidence
CI / test (push) Successful in 1m18s
CI / test (pull_request) Successful in 1m18s
2026-08-26 09:47:49 +03:00
m 515a98c470 Merge pull request 'Preserve distance context before search normalization' (#400) from codex/household-distance-context into main
CI / test (push) Successful in 1m32s
Reviewed-on: #400
2026-08-26 06:38:01 +00:00
m d3ad1fd5bb Preserve distance context before search normalization
CI / test (push) Successful in 1m23s
CI / test (pull_request) Successful in 1m20s
2026-08-26 09:34:43 +03:00
m e1802aef12 Merge pull request 'Answer directly without repeating the question' (#399) from codex/household-direct-answer into main
CI / test (push) Successful in 1m34s
Reviewed-on: #399
2026-08-26 06:23:34 +00:00
2 changed files with 39 additions and 2 deletions
+18 -2
View File
@@ -811,9 +811,13 @@ func main() {
continue
}
learnedLexicon := interactiondomain.TaskLexiconFromHistory(conversationHistory)
searchQuery := interactiondomain.SearchQueryWithLexicon(part, learnedLexicon)
// Preserve the original utterance for semantic route compilation
// before removing a search imperative. Distance and route skills
// need the user's relation words (for example "до") to bind a
// remembered current location to the requested destination.
searchQuery := interactiondomain.TravelResearchQuery(part, conversationHistory, now)
searchQuery = interactiondomain.SearchQueryWithLexicon(searchQuery, learnedLexicon)
searchQuery = interactiondomain.TimeDifferenceResearchQuery(searchQuery)
searchQuery = interactiondomain.TravelResearchQuery(searchQuery, conversationHistory, now)
// The research capability may try its configured source and a
// source-recovery fallback. Its caller must leave enough budget for
// both attempts and evidence evaluation.
@@ -1843,6 +1847,9 @@ func researchFindingMatchesIntent(query string, finding epistemics.ResearchFindi
if ticketSearchQuery(query) && !ticketFindingMatchesDestination(query, finding) {
return false
}
if distanceResearchQuery(query) && !containsDistanceEvidence(finding.Excerpt.Text) {
return false
}
if !nearestFlightQuery(query) {
return true
}
@@ -1872,6 +1879,15 @@ func researchFindingMatchesIntent(query string, finding epistemics.ResearchFindi
return true
}
func distanceResearchQuery(query string) bool {
lower := strings.ToLower(query)
return strings.Contains(lower, "расстоян") || strings.Contains(lower, "километр")
}
func containsDistanceEvidence(value string) bool {
return regexp.MustCompile(`(?i)\b\d[\d\s]*\s*(?:км|километр)`).MatchString(value)
}
func ticketSearchQuery(query string) bool {
return interactiondomain.TicketSearchDestination(query) != ""
}
+21
View File
@@ -70,6 +70,18 @@ func TestTicketReplyRejectsGenericCategoryPageWithoutDestination(t *testing.T) {
}
}
func TestDistanceReplyRejectsCalculatorPageWithoutDistance(t *testing.T) {
query := "расстояние между Москве и Сочи в километрах по прямой и по дороге"
calculator := epistemics.ResearchFinding{Source: epistemics.Source{Title: "Расчет расстояний"}, Excerpt: epistemics.SourceExcerpt{Text: "Калькулятор рассчитывает точное расстояние между городами."}}
if researchFindingMatchesIntent(query, calculator) {
t.Fatal("distance calculator landing page was presented without a measured distance")
}
measured := epistemics.ResearchFinding{Source: epistemics.Source{Title: "Маршрут"}, Excerpt: epistemics.SourceExcerpt{Text: "Расстояние по дороге составляет 1 620 км."}}
if !researchFindingMatchesIntent(query, measured) {
t.Fatal("measured distance evidence was rejected")
}
}
func TestResearchReplyRejectsGenericLandingPageForConcreteIdentifier(t *testing.T) {
result := epistemics.ResearchResult{Findings: []epistemics.ResearchFinding{{
State: epistemics.FindingSupported,
@@ -101,6 +113,15 @@ func TestResearchIdentifiersExcludeSearchDate(t *testing.T) {
}
}
func TestResearchQueryKeepsDistanceRelationBeforeSearchNormalization(t *testing.T) {
history := []interaction.HumanUtterance{{Content: "я сейчас в Москве"}}
query := interactiondomain.TravelResearchQuery("сколько километров до Сочи?", history, time.Time{})
query = interactiondomain.SearchQueryWithLexicon(query, interactiondomain.TaskLexicon{})
if query != "расстояние между Москве и Сочи в километрах по прямой и по дороге" {
t.Fatalf("distance query lost remembered origin: %q", query)
}
}
func TestResponseReviewPreservesAttemptedResearchOutcome(t *testing.T) {
if reviewMayReplacePlanningReply(false, false, true, false, "Уточните аэропорт.", "Пока не смог получить проверяемый ответ.") {
t.Fatal("review replaced an honest unbacked research outcome")