Why: Goal-sensitive workflow verification persisted model prompts and prior output text in trusted receipt rows, while cross-step model inputs could reuse stale machine output. Evidence: RED receipt privacy test; full Go suite, targeted race, isolated PostgreSQL store/runmgr/storage-migrate tests, vet, and static build passed locally before commit. A known unrelated TempDir cleanup flake failed once and passed on targeted and serial full replay. Impact: Add optional same-provider source recheck, verify every included item and evidence body before reuse, gate cross-step outputs, reject unsettled attempts, remove raw scope columns, scrub isolated candidate v34 SQLite/PG schemas, and reject unsafe backups. Refs: Approved RDM stage6 W6 source-recheck design adjustment r1; W6 independent review.
51 lines
2.3 KiB
Go
51 lines
2.3 KiB
Go
package projectcontext
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"agent-system-backend/pkg/extension"
|
|
)
|
|
|
|
func TestAssembleOffersOnlyBudgetedEvidenceReferences(t *testing.T) {
|
|
bundle := extension.ProjectContextBundle{Status: extension.ProjectContextReady, ProjectID: "p1", Evidence: []extension.ProjectEvidenceRef{{ID: "ref-1", SourceID: "doc-1", Revision: "r2", Hash: "h1"}, {ID: strings.Repeat("x", 1000), SourceID: "doc-2", Revision: "r2", Hash: "h2"}}}
|
|
text, manifest, err := Assemble(bundle, 180)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(text, "ref-1") || strings.Contains(text, strings.Repeat("x", 1000)) || len(manifest.OfferedReferences) != 1 || manifest.OfferedReferences[0].ID != "ref-1" {
|
|
t.Fatalf("reference offer does not match model input: text=%q manifest=%+v", text, manifest)
|
|
}
|
|
}
|
|
|
|
func TestValidateCurrentRejectsWithdrawnOfferedReference(t *testing.T) {
|
|
ref := extension.ProjectEvidenceRef{ID: "ref-1", SourceID: "doc-1", Revision: "r2", Hash: "h1"}
|
|
old := extension.ProjectContextBundle{Status: extension.ProjectContextReady, ProjectID: "p1", Evidence: []extension.ProjectEvidenceRef{ref}}
|
|
_, manifest, err := Assemble(old, 180)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
current := extension.ProjectContextBundle{Status: extension.ProjectContextReady, ProjectID: "p1"}
|
|
if err := ValidateCurrent(manifest, current); err == nil {
|
|
t.Fatal("reference withdrawn before model send was still offered")
|
|
}
|
|
}
|
|
|
|
func TestAssembleIncludesUnresolvedMissingStatus(t *testing.T) {
|
|
bundle := extension.ProjectContextBundle{Status: extension.ProjectContextReady, ProjectID: "p1", Missing: []string{"unresolved conflict"}}
|
|
text, manifest, err := Assemble(bundle, 180)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(text, "unresolved conflict") || len(manifest.Missing) != 1 {
|
|
t.Fatalf("missing status hidden from model or receipt: text=%q manifest=%+v", text, manifest)
|
|
}
|
|
}
|
|
|
|
func TestAssembleRejectsRequiredSourceWithoutStableRevisionAndHash(t *testing.T) {
|
|
bundle := extension.ProjectContextBundle{Status: extension.ProjectContextReady, ProjectID: "p1", Items: []extension.ProjectContextItem{{SourceID: "legacy", Text: "private", Required: true}}}
|
|
if _, _, err := Assemble(bundle, 900); err == nil {
|
|
t.Fatal("legacy source without revision/hash entered recoverable project model input")
|
|
}
|
|
}
|