2c27e2ce1f
The "address him as ты" rule had only reached two of the five system prompts. Instead of pasting it into the other three (five copies drift — that is how this happened), there is now one block, in internal/persona, prepended to all five: nudges, action replies, chat, note queries and general knowledge. The block says who he is and how to address him (a man, always "ты", never "вы", never "он" about him; Maven stays feminine), plus the current local date and time. It is rendered fresh each turn because the time changes, and it is correct with an empty config — the address and gender rules are defaults in code. Config only adds optional facts: owner_name, city, and the existing free-text `persona` string, which is now the static half of the block. Russian even in front of the English prompts: the rules are Russian grammar, so they read best stated in Russian, and there is one copy. Vikunja #394. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CGeSZxh1DCtRxmFVSYVGvJ
51 lines
1.5 KiB
Go
51 lines
1.5 KiB
Go
package persona
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
var ref = time.Date(2026, 7, 31, 14, 5, 0, 0, time.UTC)
|
|
|
|
// The block must be correct with an empty config: the address form and the
|
|
// gender rules are hard constraints, not preferences.
|
|
func TestBlockWorksWithZeroConfig(t *testing.T) {
|
|
b := Facts{}.Block(ref)
|
|
for _, want := range []string{"женском роде", "ОБРАЩЕНИЕ", "\"ты\"", "31 июля 2026", "пятница", "14:05"} {
|
|
if !strings.Contains(b, want) {
|
|
t.Errorf("block missing %q:\n%s", want, b)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBlockAddsOptionalFacts(t *testing.T) {
|
|
b := Facts{OwnerName: "Ками", City: "Москва", Static: "Будь краткой."}.Block(ref)
|
|
for _, want := range []string{"Ками", "Москва", "Будь краткой."} {
|
|
if !strings.Contains(b, want) {
|
|
t.Errorf("block missing %q:\n%s", want, b)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The time changes between turns, so two renders must differ.
|
|
func TestBlockRendersTimePerTurn(t *testing.T) {
|
|
a := Facts{}.Block(ref)
|
|
c := Facts{}.Block(ref.Add(time.Hour))
|
|
if a == c {
|
|
t.Errorf("block did not change with the clock:\n%s", a)
|
|
}
|
|
}
|
|
|
|
func TestPrependNilIsSafe(t *testing.T) {
|
|
if got := Prepend(nil, "PROMPT"); got != "PROMPT" {
|
|
t.Errorf("Prepend(nil) = %q", got)
|
|
}
|
|
if got := Prepend(func() string { return " " }, "PROMPT"); got != "PROMPT" {
|
|
t.Errorf("Prepend(blank) = %q", got)
|
|
}
|
|
if got := Prepend(func() string { return "CTX" }, "PROMPT"); got != "CTX\n\nPROMPT" {
|
|
t.Errorf("Prepend = %q", got)
|
|
}
|
|
}
|