mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-10-21 14:52:05 +02:00
65 lines
2.6 KiB
Go
65 lines
2.6 KiB
Go
package project
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"cyberstrike-ai/internal/config"
|
|
"cyberstrike-ai/internal/database"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func TestBlackboardWorkingMemoryIsConversationScopedIncludingEdges(t *testing.T) {
|
|
db, err := database.NewDB(filepath.Join(t.TempDir(), "scope.db"), zap.NewNop())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
p, err := db.CreateProject(&database.Project{Name: "scope"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, f := range []*database.ProjectFact{
|
|
{ProjectID: p.ID, FactKey: "finding/shared", Category: "finding", Confidence: "confirmed", Summary: "shared result", Body: "RAW_SHARED"},
|
|
{ProjectID: p.ID, FactKey: "note/context-a", SourceConversationID: "a", Summary: "progress a", Body: "RAW_A"},
|
|
{ProjectID: p.ID, FactKey: "note/context-b", SourceConversationID: "b", Summary: "progress b", Body: "RAW_B", Pinned: true, Confidence: "confirmed"},
|
|
{ProjectID: p.ID, FactKey: "note/context-unknown", Summary: "unknown origin", Pinned: true},
|
|
{ProjectID: p.ID, FactKey: "note/manual", SourceConversationID: "b", Summary: "shared manual note"},
|
|
} {
|
|
if _, err := db.UpsertProjectFact(f); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if _, err := db.AddProjectFactEdge(p.ID, database.ProjectFactEdgeInput{To: "finding/shared", Type: "supports"}, "note/context-b", "b"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cfg := config.ProjectConfig{Enabled: true, FactIndexMaxRunes: 3500, FactIndexPathMaxRunes: 1000}
|
|
for _, conv := range []string{"a", "b", ""} {
|
|
block, err := BuildFactIndexBlock(db, p.ID, cfg, conv)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(block, "finding/shared") || !strings.Contains(block, "note/manual") || strings.Contains(block, "note/context-unknown") || strings.Contains(block, "RAW_") {
|
|
t.Fatalf("scope altered shared facts or injected bodies: %s", block)
|
|
}
|
|
for _, source := range []string{"a", "b"} {
|
|
if strings.Contains(block, "note/context-"+source) != (source == conv) {
|
|
t.Fatalf("conversation %q mixes source %q: %s", conv, source, block)
|
|
}
|
|
}
|
|
if len([]rune(block)) > cfg.FactIndexMaxRunes {
|
|
t.Fatal("scope labels escaped index budget")
|
|
}
|
|
}
|
|
generic, err := BuildFactIndexBlock(db, p.ID, cfg)
|
|
if err != nil || strings.Contains(generic, "note/context-") {
|
|
t.Fatalf("missing conversation defaults to global working memory: %s %v", generic, err)
|
|
}
|
|
// Human/admin raw queries retain the existing project-wide data view.
|
|
raw, err := db.ListProjectFacts(p.ID, database.ProjectFactListFilter{}, 100, 0)
|
|
if err != nil || len(raw) != 5 {
|
|
t.Fatalf("scope destroyed or globally hid stored notes: %v %v", raw, err)
|
|
}
|
|
}
|