All checks were successful
release-tag / release-image (push) Successful in 2m19s
82 lines
3.1 KiB
Go
82 lines
3.1 KiB
Go
package engine
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/local/glpi-neural-brain/internal/graph"
|
|
"github.com/local/glpi-neural-brain/internal/model"
|
|
)
|
|
|
|
func TestBuildAutonomousCandidatesPrioritizesContradictionWithoutEvidence(t *testing.T) {
|
|
now := time.Now().UTC()
|
|
snapshot := model.Snapshot{
|
|
Nodes: []model.Node{
|
|
{ID: "a", Kind: "knowledge", Label: "ZFS Restore", Status: "production", UpdatedAt: now.Add(-400 * 24 * time.Hour), Metadata: map[string]any{"source": "internal-category"}},
|
|
{ID: "b", Kind: "knowledge", Label: "ZFS Key Import", Status: "production", UpdatedAt: now, Metadata: map[string]any{"source": "internal-category"}},
|
|
},
|
|
Edges: []model.Edge{{ID: "e", Source: "a", Target: "b", Type: "contradicts", Status: "accepted"}},
|
|
}
|
|
candidates := buildAutonomousCandidates(snapshot, graph.NodeFilter{Sources: []string{"internal-category"}}, 8)
|
|
if len(candidates) == 0 {
|
|
t.Fatal("expected a research candidate")
|
|
}
|
|
candidate := candidates[0]
|
|
if candidate.Priority < .75 {
|
|
t.Fatalf("expected contradiction/no-evidence candidate to be high priority, got %.3f", candidate.Priority)
|
|
}
|
|
if len(candidate.SeedNodeIDs) < 2 {
|
|
t.Fatalf("expected related production nodes as seeds, got %#v", candidate.SeedNodeIDs)
|
|
}
|
|
if got := candidate.Signals["contradictions"]; got != 1 {
|
|
t.Fatalf("expected contradiction signal, got %#v", got)
|
|
}
|
|
}
|
|
|
|
func TestBuildAutonomousCandidatesHonorsExactThinkingSource(t *testing.T) {
|
|
snapshot := model.Snapshot{Nodes: []model.Node{
|
|
{ID: "a", Kind: "knowledge", Label: "Allowed", Status: "production", Metadata: map[string]any{"source": "internal-category"}},
|
|
{ID: "b", Kind: "knowledge", Label: "Wrong case", Status: "production", Metadata: map[string]any{"source": "Internal-Category"}},
|
|
}}
|
|
candidates := buildAutonomousCandidates(snapshot, graph.NodeFilter{Sources: []string{"internal-category"}}, 8)
|
|
for _, candidate := range candidates {
|
|
if candidate.Topic == "Wrong case" {
|
|
t.Fatal("candidate source matching must stay exact and case-sensitive")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBuildAutonomousQueryQueueUsesBothLanguagesAndRounds(t *testing.T) {
|
|
queue := buildAutonomousQueryQueue(
|
|
[]string{"Wie wird ein Restore validiert?", "Welche Schlüssel werden benötigt?"},
|
|
[]string{"ZFS Restore validieren", "ZFS Schlüssel importieren", "ZFS Ersatzsystem"},
|
|
[]string{"ZFS restore validation", "ZFS key import"},
|
|
3,
|
|
)
|
|
if len(queue) != 5 {
|
|
t.Fatalf("expected five planned queries, got %d", len(queue))
|
|
}
|
|
languages := map[string]bool{}
|
|
maxRound := 0
|
|
for _, item := range queue {
|
|
languages[item.Language] = true
|
|
if item.Round > maxRound {
|
|
maxRound = item.Round
|
|
}
|
|
}
|
|
if !languages["de-DE"] || !languages["en-US"] {
|
|
t.Fatalf("expected German and English queries, got %#v", languages)
|
|
}
|
|
if maxRound < 2 || maxRound > 3 {
|
|
t.Fatalf("unexpected round assignment: %d", maxRound)
|
|
}
|
|
}
|
|
|
|
func TestAutonomousDedupeKeyIsStableAcrossSeedOrder(t *testing.T) {
|
|
a := autonomousDedupeKey(" ZFS Restore ", []string{"b", "a"})
|
|
b := autonomousDedupeKey("zfs restore", []string{"a", "b"})
|
|
if a != b {
|
|
t.Fatalf("dedupe key should normalize topic spacing/case and seed order: %q != %q", a, b)
|
|
}
|
|
}
|