Files
Maven/cmd/mavend/weatherq_test.go
T
claude 26d6d71588 mavend, router: stop three sources claiming turns the world should answer (V-474)
The querySources order predates the 2026-08-02 ruling that live search leads.

An unconfigured feeds source claimed every news question and answered with a
configuration status, so "что происходит сейчас в новостях про искусственный
интеллект?" never reached the search sitting one source below. It now claims
only when neither SearXNG nor the ZIMs are configured, which is the case the
"не читаю ленты" line was written for — general knowledge would otherwise
invent a bulletin.

The calendar matches on a day word alone and sits above the weather, so
"какая сегодня погода в Москве?" answered "на 02.08.2026 ничего нет." It now
steps aside on weather wording, the same bail-out queryHome already does.

"что нового в лентах?" routed system and answered "пока не умею", while the
same question worded with "новостях" worked. FeedQueryGrammar routes it to
query at stage 0, requiring an ask word and a feed noun so the bare greeting
"что нового?" stays a greeting. Wired in the eval too, since the fixture is
only worth anything while its grammar set is the daemon's.

Also: the claiming source is now logged. /trace is the nudge-rule trace and
carries no query-source field, so a wrong answer could not be told apart from
a wrongly-ordered chain.

Kiwix having no live coverage is filed separately as V-508 — it is a decision
about search quality, not an ordering fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 04:00:58 +04:00

66 lines
2.6 KiB
Go

package main
import (
"context"
"testing"
"github.com/kami/maven/internal/router"
)
// TestExtractWeatherLocation — any place he names comes through, not just the
// six that used to be in a table (Vikunja #421).
func TestExtractWeatherLocation(t *testing.T) {
cases := []struct {
utterance string
def string
want string
}{
// The cities the table had, and the ones it silently dropped.
{"какая погода в Москве", "Berlin", "Москве"},
{"какая погода в Казани", "Berlin", "Казани"},
{"погода в Тбилиси?", "Berlin", "Тбилиси"},
{"what's the weather in New York", "Berlin", "New York"},
{"тепло в Нижнем Новгороде?", "Berlin", "Нижнем Новгороде"},
// He named nothing: the configured default, and nothing at all when
// there is no default.
{"какая сегодня погода", "Berlin", "Berlin"},
{"какая сегодня погода", "", ""},
// "в" followed by something that is not a place stays the default —
// the house sensors and the day words answer elsewhere.
{"тепло в комнате?", "Berlin", "Berlin"},
{"какая погода в выходные", "Berlin", "Berlin"},
}
for _, c := range cases {
if got := extractWeatherLocation(c.utterance, c.def); got != c.want {
t.Errorf("extractWeatherLocation(%q, %q) = %q, want %q", c.utterance, c.def, got, c.want)
}
}
}
// TestCalendarStepsAsideForWeather — the defect (Vikunja #474). "какая сегодня
// погода в Москве?" answered "на 02.08.2026 ничего нет.": the calendar matches
// on a day word alone, and it sits above the weather source.
func TestCalendarStepsAsideForWeather(t *testing.T) {
h, api := contQueryHandler()
for _, u := range []string{
"какая сегодня погода в Москве?",
"будет дождь завтра?",
"сколько градусов сегодня?",
} {
if reply, ok := h.queryCalendar(context.Background(), &queryTurn{
dec: router.Decision{Intent: router.IntentQuery, Utterance: u},
}); ok {
t.Errorf("the calendar claimed %q with %q", u, reply)
}
}
if api.events != 0 {
t.Errorf("CalendarEvents called %d times for weather questions, want 0", api.events)
}
// The agenda question it exists for still reaches it.
if _, ok := h.queryCalendar(context.Background(), &queryTurn{
dec: router.Decision{Intent: router.IntentQuery, Utterance: "что у меня сегодня?"},
}); !ok {
t.Fatal("the calendar stopped answering the agenda question")
}
}