package audit_test import ( "context" "testing" "gitea.stevedudenhoeffer.com/steve/majordomo/llm" "gitea.stevedudenhoeffer.com/steve/majordomo/provider/fake" "gitea.stevedudenhoeffer.com/steve/executus/audit" "gitea.stevedudenhoeffer.com/steve/executus/run" "gitea.stevedudenhoeffer.com/steve/executus/tool" ) // TestAuditBatteryEndToEnd wires the audit battery (Memory storage) into // run.Ports.Audit, runs an agent, and verifies the run was recorded and is // queryable — proving Sink/Writer/Memory satisfy the core seams end to end. func TestAuditBatteryEndToEnd(t *testing.T) { mem := audit.NewMemory() fp := fake.New("fake") fp.Enqueue("m", fake.Reply("the answer")) m, err := fp.Model("m") if err != nil { t.Fatal(err) } ex := run.New(run.Config{ Registry: tool.NewRegistry(), Models: func(ctx context.Context, _ string) (context.Context, llm.Model, error) { return ctx, m, nil }, Ports: run.Ports{Audit: audit.NewSink(mem)}, }) res := ex.Run(context.Background(), run.RunnableAgent{ID: "agent-1", Name: "a", ModelTier: "m"}, tool.Invocation{RunID: "run-xyz", CallerID: "caller-1"}, "question") if res.Err != nil { t.Fatalf("run error: %v", res.Err) } // The run was recorded with a terminal status + output. got, err := mem.GetRun(context.Background(), "run-xyz") if err != nil { t.Fatalf("GetRun: %v", err) } if got.Status != "ok" { t.Errorf("status = %q, want ok", got.Status) } if got.Output != "the answer" { t.Errorf("output = %q, want %q", got.Output, "the answer") } if got.FinishedAt == nil { t.Error("FinishedAt should be set after the run") } if got.SkillID != "agent-1" { t.Errorf("SkillID = %q, want agent-1 (the subject id)", got.SkillID) } // And it is queryable by caller. runs, err := mem.ListRunsByCaller(context.Background(), "caller-1", 10) if err != nil { t.Fatalf("ListRunsByCaller: %v", err) } if len(runs) != 1 || runs[0].ID != "run-xyz" { t.Errorf("ListRunsByCaller = %+v, want [run-xyz]", runs) } } // TestNilSinkRecordsNothing: NewSink(nil) is equivalent to no audit. func TestNilSinkRecordsNothing(t *testing.T) { s := audit.NewSink(nil) if rec := s.StartRun(context.Background(), run.RunInfo{RunID: "r"}); rec != nil { t.Error("NewSink(nil).StartRun should return a nil recorder") } }