Files
Agent-System-Backend/internal/runmgr/project_work_retrieval_test.go
weichen da4b8c9956 Gate project runs and replies on source analysis
Why: Project messages, retrieved evidence, tool results, and final replies must not affect model work or reach users before the domain risk decision is complete.

Evidence: RED tests proved the runner, final reply, and message deltas advanced before the gate; focused tests, go test -p 1 ./..., go build ./..., and isolated PostgreSQL runtime tests now pass.

Impact: Wire the optional RDM observer into project run start, retrieval, tool-result, HITL clarification, and final reply buffering; hosts without the optional provider keep existing behavior.

Refs: TT-N03, TT-R01; approved work-observation design and stage-five plan
2026-10-14 16:54:13 +00:00

59 lines
2.2 KiB
Go

package runmgr
import (
"context"
"path/filepath"
"testing"
"agent-system-backend/internal/store"
core "agent-system-core"
)
func TestProjectRetrievalRecordsEachActualAuthorizedHit(t *testing.T) {
st, err := store.OpenSQLite(filepath.Join(t.TempDir(), "retrieval.db"))
if err != nil {
t.Fatal(err)
}
defer st.Close()
if err := st.EnsureUser("alice", "Alice"); err != nil {
t.Fatal(err)
}
project, err := st.CreateProject("alice", "P")
if err != nil {
t.Fatal(err)
}
conv, err := st.CreateConversation("alice", string(project.ID), "Work", "")
if err != nil {
t.Fatal(err)
}
run := core.Run{ConversationID: conv.ID, ProjectID: project.ID, Owner: "alice", Kind: core.RunConversation, Status: core.RunRunning, Phase: core.PhaseThinking}
if err := st.CreateRun(&run); err != nil {
t.Fatal(err)
}
mgr := New(st, nil, nil, nil, nil, nil, nil, nil, nil)
fr := &sharedFakeRetriever{own: []core.RetrievalHit{
{Doc: core.KnowledgeDoc{ID: "k1", Owner: "alice", ProjectID: project.ID, Ref: "https://example.test/a", Chunk: "source A"}, Kind: "fulltext"},
{Doc: core.KnowledgeDoc{ID: "k2", Owner: "alice", ProjectID: project.ID, Ref: "https://example.test/b", Chunk: "source B"}, Kind: "fulltext"},
}}
mgr.SetRetriever(fr)
enableProjectGateForTest(mgr)
rc := &runCtx{mgr: mgr, run: run, ctx: context.Background()}
hits, err := rc.Retrieve(core.RetrievalQuery{Text: "test", ProjectID: project.ID})
if err != nil || len(hits) != 2 {
t.Fatalf("authorized results not returned: %+v %v", hits, err)
}
rows, err := st.PendingProjectWorkObservations(10)
if err != nil || len(rows) != 2 {
t.Fatalf("actual hits not individually captured: %+v %v", rows, err)
}
for _, row := range rows {
if row.SourceKind != "retrieval-hit" || row.Owner != "alice" || row.RunID != string(run.ID) || row.Metadata["query"] != "test" || row.Text == "" {
t.Fatalf("retrieval source missing trusted identity or actual text: %+v", row)
}
}
fr.own = []core.RetrievalHit{{Doc: core.KnowledgeDoc{Chunk: "no stable ID"}}}
if hits, err := rc.Retrieve(core.RetrievalQuery{Text: "test", ProjectID: project.ID}); err == nil || hits != nil {
t.Fatalf("source without stable ID entered model input: %+v %v", hits, err)
}
}