Files
weichen ecb86f4309 Recheck project workflow sources without storing prompts
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.
2026-10-14 05:38:11 +00:00

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")
}
}