package store import ( "crypto/sha256" "path/filepath" "testing" "time" "agent-system-backend/pkg/extension" core "agent-system-core" ) func TestWorkflowStepSourceRequiresRespondedManifestAndExactRunStep(t *testing.T) { st, err := OpenSQLite(filepath.Join(t.TempDir(), "step.db")) if err != nil { t.Fatal(err) } defer st.Close() p, err := st.CreateProject("alice", "P") if err != nil { t.Fatal(err) } c, err := st.CreateConversation("alice", string(p.ID), "C", "") if err != nil { t.Fatal(err) } r := core.Run{Owner: "alice", ConversationID: c.ID, ProjectID: p.ID, Kind: core.RunConversation, Status: core.RunPending} if err := st.CreateRun(&r); err != nil { t.Fatal(err) } started := time.Now().Add(-time.Second) m := extension.ProjectContextManifest{ProjectID: p.ID, AttemptID: "attempt-1", WorkflowStepAttemptID: "engine-run/draft/1", Delivery: "attempted", InputSHA256: "input", AuthorizationEpoch: "duty-1", PublicationEpoch: "pub-1", Watermark: "w1"} scope := ContextManifestScope{Bound: true} if err := st.AppendContextManifestWithScope("alice", string(r.ID), m, scope); err != nil { t.Fatal(err) } if _, err := st.BindWorkflowStepSource("alice", string(r.ID), "draft", "engine-run/draft/1", "prompt", started, []byte("old body")); err == nil { t.Fatal("unanswered model attempt bound output") } unrelated := m unrelated.AttemptID = "other-model-attempt" unrelated.WorkflowStepAttemptID = "engine-run/other/1" if err := st.AppendContextManifestWithScope("alice", string(r.ID), unrelated, scope); err != nil { t.Fatal(err) } unrelated.Delivery = "responded" if err := st.AppendContextManifestWithScope("alice", string(r.ID), unrelated, scope); err != nil { t.Fatal(err) } if _, err := st.BindWorkflowStepSource("alice", string(r.ID), "draft", "engine-run/draft/1", "prompt", started, []byte("old body")); err == nil { t.Fatal("another step's responded attempt bound draft output") } m.Delivery = "responded" if err := st.AppendContextManifestWithScope("alice", string(r.ID), m, scope); err != nil { t.Fatal(err) } bound, err := st.BindWorkflowStepSource("alice", string(r.ID), "draft", "engine-run/draft/1", "prompt", started, []byte("old body")) if err != nil || bound.AttemptID != "attempt-1" || bound.StepAttemptID != "engine-run/draft/1" || bound.OutputSHA256 != sha256.Sum256([]byte("old body")) { t.Fatalf("source binding missed actual output: %+v err=%v", bound, err) } if _, err := st.WorkflowStepSource("alice", string(r.ID), "other"); err == nil { t.Fatal("another step reused output binding") } if _, err := st.WorkflowStepSource("bob", string(r.ID), "draft"); err == nil { t.Fatal("another owner read output binding") } if _, err := st.BindWorkflowStepSource("alice", string(r.ID), "tool", "engine-run/tool/1", "tool", started, []byte("tool body")); err == nil { t.Fatal("tool output bound as model-sourced material") } legacy := m legacy.AttemptID, legacy.WorkflowStepAttemptID, legacy.Delivery = "legacy-model", "engine-run/legacy/1", "attempted" if err := st.AppendContextManifest("alice", string(r.ID), legacy); err != nil { t.Fatal(err) } legacy.Delivery = "responded" if err := st.AppendContextManifest("alice", string(r.ID), legacy); err != nil { t.Fatal(err) } if _, err := st.BindWorkflowStepSource("alice", string(r.ID), "legacy", "engine-run/legacy/1", "prompt", started, []byte("legacy body")); err == nil { t.Fatal("model receipt without bound original Resolve scope became a workflow source") } unknown := m unknown.AttemptID, unknown.Delivery = "unknown-model-attempt", "attempted" if err := st.AppendContextManifestWithScope("alice", string(r.ID), unknown, scope); err != nil { t.Fatal(err) } unknown.Delivery = "unknown" if err := st.AppendContextManifestWithScope("alice", string(r.ID), unknown, scope); err != nil { t.Fatal(err) } if _, err := st.RespondedWorkflowStepManifests("alice", string(r.ID), "engine-run/draft/1"); err == nil { t.Fatal("unknown model attempt hidden by earlier responded attempt") } if _, err := st.BindWorkflowStepSource("alice", string(r.ID), "draft", "engine-run/draft/1", "prompt", started, []byte("old body")); err == nil { t.Fatal("unknown model attempt rebound completed step") } if err := st.UnbindWorkflowStepSource("alice", string(r.ID), "draft"); err != nil { t.Fatal(err) } if _, err := st.WorkflowStepSource("alice", string(r.ID), "draft"); err == nil { t.Fatal("retry retained an earlier source binding") } }