e481ad4930
The capability was built, wired and degrading correctly, and no utterance could reach it. Its aliases sit on the act dispatch, "что требует внимания" routes to a query, and every query source passed — so the turn fell to the web search and came back with an article about the concept of attention. That reads as an answer, which is worse than silence. queryAttention sits next to "tasks", above the recall sources and well above the personal boundary: it is operational state about his things, and a notes pass would otherwise answer from whatever he once wrote about a server. It calls the same handler the act path calls, so the outage string comes free. An absent or unconfigured Praxis falls through instead of claiming the turn, like queryHome and queryNetwork. A configured Praxis that is down claims it and names the gap. "что нового" is left to the feeds source.
78 lines
2.5 KiB
Go
78 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/kami/maven/internal/router"
|
|
)
|
|
|
|
func TestIsAttentionQuery(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
text string
|
|
want bool
|
|
}{
|
|
{"что требует внимания", true},
|
|
{"на что обратить внимание?", true},
|
|
{"что не так?", true},
|
|
{"что важного?", true},
|
|
// The feeds source owns this one, and should keep owning it.
|
|
{"что нового?", false},
|
|
{"какая погода?", false},
|
|
{"", false},
|
|
} {
|
|
if got := isAttentionQuery(tc.text); got != tc.want {
|
|
t.Errorf("isAttentionQuery(%q) = %v, want %v", tc.text, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestAttentionQuestionReachesPraxis — the defect (Vikunja #475). The question
|
|
// routes to IntentQuery, and every source used to pass, so a web search about
|
|
// the concept of attention answered it.
|
|
func TestAttentionQuestionReachesPraxis(t *testing.T) {
|
|
ctx := context.Background()
|
|
praxis := newFakePraxis(t, fixturePraxisAttentionItems(map[string]any{
|
|
"id": "item_1", "title": "disk almost full", "importance": 3.0,
|
|
}))
|
|
h := ecoHandler(t, nil, praxis, nil)
|
|
|
|
reply, ok := h.queryAttention(ctx, &queryTurn{dec: router.Decision{
|
|
Intent: router.IntentQuery, Utterance: "что требует внимания",
|
|
}})
|
|
if !ok {
|
|
t.Fatal("the attention question must be claimed before the world sources")
|
|
}
|
|
if !strings.Contains(reply, "disk almost full") {
|
|
t.Fatalf("reply = %q, want the praxis item", reply)
|
|
}
|
|
}
|
|
|
|
// A configured Praxis that is down claims the turn and says so. Falling
|
|
// through here would answer an outage with an encyclopedia article.
|
|
func TestAttentionQuestionSaysWhenPraxisIsDown(t *testing.T) {
|
|
ctx := context.Background()
|
|
praxis := newFakePraxis(t, fixturePraxisAttentionItems())
|
|
h := ecoHandler(t, nil, praxis, nil)
|
|
praxis.SetFault(503)
|
|
|
|
reply, ok := h.queryAttention(ctx, &queryTurn{dec: router.Decision{
|
|
Intent: router.IntentQuery, Utterance: "что требует внимания",
|
|
}})
|
|
if !ok || !strings.Contains(reply, "не могу") {
|
|
t.Fatalf("an outage must name the gap, got ok=%v reply=%q", ok, reply)
|
|
}
|
|
}
|
|
|
|
// No Praxis configured means no claim: the rest of the chain still runs.
|
|
func TestAttentionQuestionFallsThroughWithoutPraxis(t *testing.T) {
|
|
h, _ := newFactGateHandler(t, time.Now())
|
|
if _, ok := h.queryAttention(context.Background(), &queryTurn{dec: router.Decision{
|
|
Intent: router.IntentQuery, Utterance: "что требует внимания",
|
|
}}); ok {
|
|
t.Fatal("an unconfigured praxis must not claim the turn")
|
|
}
|
|
}
|