afac8fb670
The checks stay in the eval package and the daemon calls three of them: feminine, address, and a new leaked-reasoning test. No retry — it doubles the latency on the turn that is already going badly, and on the nudge path the moment has passed. A failure falls back to the deterministic floor and is logged with the whole rejected text and counted by check name. hisgender is deliberately not run: the simulator showed it rejecting "записала, что ты выпил воды", which is her own correct self-reference.
76 lines
2.3 KiB
Go
76 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/kami/maven/internal/delivery"
|
|
"github.com/kami/maven/internal/loop"
|
|
)
|
|
|
|
func TestGuardPassesWhatSheShouldSay(t *testing.T) {
|
|
good := []string{
|
|
"записала: купить хлеб.",
|
|
"поняла, напомню в 11:00.",
|
|
"ты не пил воду с утра.",
|
|
"я рада, что получилось.",
|
|
"",
|
|
}
|
|
for _, body := range good {
|
|
if check, ok := guardSpoken("test", body); !ok {
|
|
t.Errorf("guardSpoken(%q) rejected on %s", body, check)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGuardStopsWhatSheShouldNot(t *testing.T) {
|
|
bad := []struct {
|
|
body string
|
|
want string
|
|
}{
|
|
{"<think>он просил воду</think> попей воды.", checkLeak},
|
|
{"Thinking Process: он давно не пил.", checkLeak},
|
|
{`{"response": "попей воды", "mood": "neutral"}`, checkLeak},
|
|
{"я напомнил тебе про воду.", "feminine"},
|
|
{"вы давно не пили воду.", "address"},
|
|
}
|
|
for _, c := range bad {
|
|
check, ok := guardSpoken("test", c.body)
|
|
if ok {
|
|
t.Errorf("guardSpoken(%q) let it through", c.body)
|
|
continue
|
|
}
|
|
if check != c.want {
|
|
t.Errorf("guardSpoken(%q) failed on %s; want %s", c.body, check, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGuardCountsWhatItCaught(t *testing.T) {
|
|
before := personaRejectCounts()[checkLeak]
|
|
if _, ok := guardSpoken("test", "<think>…"); ok {
|
|
t.Fatal("a leaked reasoning block was let through")
|
|
}
|
|
if after := personaRejectCounts()[checkLeak]; after != before+1 {
|
|
t.Errorf("leak count %d; want %d", after, before+1)
|
|
}
|
|
}
|
|
|
|
// TestGuardNudgeFallsBackToTheFloor — a broken nudge is replaced by the
|
|
// deterministic wording, not dropped and not retried.
|
|
func TestGuardNudgeFallsBackToTheFloor(t *testing.T) {
|
|
cand := loop.Candidate{Rule: loop.Rule{Name: "water"}}
|
|
bad := delivery.PhrasedNudge{Candidate: cand, Body: "Thinking Process: он не пил.", Mood: "neutral"}
|
|
got := guardNudge(bad, cand)
|
|
if got.Body == bad.Body {
|
|
t.Fatal("the broken nudge was delivered unchanged")
|
|
}
|
|
if strings.TrimSpace(got.Body) == "" {
|
|
t.Fatal("the nudge was dropped rather than re-worded")
|
|
}
|
|
good := delivery.PhrasedNudge{Candidate: cand, Body: "попей воды.", Mood: "neutral"}
|
|
if guardNudge(good, cand).Body != good.Body {
|
|
t.Error("a good nudge was replaced")
|
|
}
|
|
}
|