package domain import ( "testing" "git.cin.su/m/Assistant/contracts/epistemics" ) func TestAcceptedReminderResponseCreatesPositiveExperienceWithoutReflection(t *testing.T) { experience, err := NewExperienceRecord(epistemics.ExperienceRecord{ SourceKind: epistemics.ExperienceSourceContinuity, OriginalIntentID: "intent-1", SourceUtteranceID: "utterance-1", ContextRefs: []epistemics.ContextRef{"continuity:attention:attention-1"}, HelpMethod: epistemics.HelpMethodDeterministicFastPath, SkillRef: "skill:obvious-reminder-response-v1", ExpectedOutcome: epistemics.OutcomeSuccess, ActualOutcome: epistemics.OutcomeSuccess, OutcomeRef: "continuity:prospective:p1", HumanResponseRef: "response-1", VerificationEvidence: []epistemics.EvidenceRef{"target-resolver:single-recent-reminder", "human-response:complete"}, ConfidenceMillis: 950, RecordedAtUnixMillis: 1000, }) if err != nil { t.Fatal(err) } if _, ok, err := ReflectionForExperience(experience); err != nil || ok { t.Fatalf("positive accepted experience should not force reflection: ok=%v err=%v", ok, err) } } func TestUserCorrectionCreatesReflectionCandidate(t *testing.T) { experience, err := NewExperienceRecord(epistemics.ExperienceRecord{ SourceKind: epistemics.ExperienceSourceInteraction, OriginalIntentID: "intent-1", SourceUtteranceID: "utterance-2", HelpMethod: epistemics.HelpMethodClarification, ExpectedOutcome: epistemics.OutcomeSuccess, ActualOutcome: epistemics.OutcomeUserCorrected, OutcomeDetail: "user corrected wrong target/project interpretation", CorrectionUtteranceID: "utterance-2", ConfidenceMillis: 1000, RecordedAtUnixMillis: 1100, }) if err != nil { t.Fatal(err) } candidate, ok, err := ReflectionForExperience(experience) if err != nil || !ok { t.Fatalf("expected reflection candidate, ok=%v err=%v", ok, err) } if candidate.Trigger != epistemics.ReflectionUserCorrection || candidate.State != epistemics.ReflectionCandidateOpen || !candidate.RequiresCognition || len(candidate.EvidenceRefs) == 0 { t.Fatalf("unexpected reflection candidate: %#v", candidate) } } func TestReflectionNormalizesExperienceIDBeforeReferencingIt(t *testing.T) { candidate, ok, err := ReflectionForExperience(epistemics.ExperienceRecord{ SourceKind: epistemics.ExperienceSourceInteraction, OriginalIntentID: "intent-1", SourceUtteranceID: "utterance-3", HelpMethod: epistemics.HelpMethodClarification, ExpectedOutcome: epistemics.OutcomeSuccess, ActualOutcome: epistemics.OutcomeFailed, OutcomeDetail: "deterministic route failed", ConfidenceMillis: 800, RecordedAtUnixMillis: 1200, }) if err != nil || !ok || candidate.SourceExperienceID == "" || !candidate.RequiresCognition { t.Fatalf("reflection did not preserve normalized source experience: candidate=%#v ok=%v err=%v", candidate, ok, err) } } func TestFastPathDeclineReturnsToThinkingInsteadOfGuessing(t *testing.T) { experience, err := FastPathDeclineExperience("intent-1", "utterance-1", "skill:obvious-reminder-response-v1", string(epistemics.OutcomeOutOfDistribution), 1200) if err != nil { t.Fatal(err) } if experience.ActualOutcome != epistemics.OutcomeOutOfDistribution || experience.HelpMethod != epistemics.HelpMethodDeterministicFastPath { t.Fatalf("unexpected fast path decline experience: %#v", experience) } candidate, ok, err := ReflectionForExperience(experience) if err != nil || !ok || candidate.Trigger != epistemics.ReflectionSampledAudit { t.Fatalf("decline should preserve reflection/escalation evidence, candidate=%#v ok=%v err=%v", candidate, ok, err) } }