Files
Assistant/tests/research_runtime/research_runtime_test.go
m 79c99289e7
CI / test (push) Successful in 24s
CI / test (pull_request) Successful in 21s
feat(epistemics): evaluate read-only research evidence
2026-08-22 14:23:17 +03:00

67 lines
3.8 KiB
Go

package research_runtime_test
import (
"context"
"testing"
"git.cin.su/m/Assistant/contracts/epistemics"
app "git.cin.su/m/Assistant/modules/epistemics/application"
domain "git.cin.su/m/Assistant/modules/epistemics/domain"
)
type connector struct {
candidates []epistemics.ResearchCandidate
}
func (c connector) Collect(context.Context, epistemics.ResearchPlan) ([]epistemics.ResearchCandidate, error) {
return c.candidates, nil
}
func candidate(statement string, freshness epistemics.FreshnessState, source, snapshot, excerpt string) epistemics.ResearchCandidate {
return epistemics.ResearchCandidate{PropositionKey: "domovoy", Statement: statement, Evidence: epistemics.EvidenceObserved,
Coverage: epistemics.CoverageComplete, Conflict: epistemics.ConflictNone,
Source: epistemics.Source{ID: epistemics.SourceID(source), Locator: "https://example.test/" + source},
Snapshot: epistemics.SourceSnapshot{ID: epistemics.SourceSnapshotID(snapshot), SourceID: epistemics.SourceID(source), ContentDigest: "sha256:" + snapshot, CapturedAtUnixMillis: 10, Freshness: freshness},
Excerpt: epistemics.SourceExcerpt{ID: epistemics.SourceExcerptID(excerpt), SnapshotID: epistemics.SourceSnapshotID(snapshot), Text: statement, Start: 0, End: int64(len(statement))}}
}
func TestResearchServiceKeepsUnknownStaleAndConflictExplicit(t *testing.T) {
plan := epistemics.ResearchPlan{ID: "plan-1", Question: "question", SourceClasses: []string{"repository"}, FreshnessPolicy: "current"}
unknown, err := (app.ResearchService{Connector: connector{}}).Evaluate(context.Background(), plan, 100)
if err != nil || len(unknown.Findings) != 1 || unknown.Findings[0].State != epistemics.FindingUnknown {
t.Fatalf("unknown evidence was not explicit: %#v %v", unknown, err)
}
result, err := (app.ResearchService{Connector: connector{candidates: []epistemics.ResearchCandidate{
candidate("one answer", epistemics.FreshnessStale, "s1", "ss1", "e1"),
candidate("another answer", epistemics.FreshnessCurrent, "s2", "ss2", "e2"),
}}}).Evaluate(context.Background(), plan, 100)
if err != nil || len(result.Findings) != 1 || result.Findings[0].State != epistemics.FindingConflicted || len(result.Findings[0].Citations) != 2 {
t.Fatalf("conflict was not retained: %#v %v", result, err)
}
}
func TestEvaluateResearchRejectsFabricatedEvidenceChain(t *testing.T) {
value := candidate("answer", epistemics.FreshnessCurrent, "s1", "ss1", "e1")
value.Excerpt.SnapshotID = "other-snapshot"
plan := epistemics.ResearchPlan{ID: "plan-1", Question: "question", SourceClasses: []string{"web"}, FreshnessPolicy: "current"}
if _, err := domain.EvaluateResearch(plan, []epistemics.ResearchCandidate{value}, 100); err != domain.ErrInvalidResearchCandidate {
t.Fatalf("fabricated evidence was accepted: %v", err)
}
}
func TestResearchServiceKeepsAssumptionAndUnknownFreshnessVisible(t *testing.T) {
plan := epistemics.ResearchPlan{ID: "plan-1", Question: "question", SourceClasses: []string{"web"}, FreshnessPolicy: "current"}
value := candidate("assumed answer", epistemics.FreshnessCurrent, "s1", "ss1", "e1")
value.Evidence = epistemics.EvidenceAssumed
result, err := (app.ResearchService{Connector: connector{candidates: []epistemics.ResearchCandidate{value}}}).Evaluate(context.Background(), plan, 100)
if err != nil || result.Findings[0].State != epistemics.FindingUnknown {
t.Fatalf("assumption was promoted: %#v %v", result, err)
}
value = candidate("unknown answer", epistemics.FreshnessUnknown, "s2", "ss2", "e2")
value.Conflict = epistemics.ConflictUnknown
result, err = (app.ResearchService{Connector: connector{candidates: []epistemics.ResearchCandidate{value}}}).Evaluate(context.Background(), plan, 100)
if err != nil || result.Findings[0].State != epistemics.FindingUnknown {
t.Fatalf("unknown freshness was promoted: %#v %v", result, err)
}
}