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
59 lines
2.2 KiB
Go
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)
|
|
}
|
|
}
|