package domain import ( "testing" "git.cin.su/m/Assistant/contracts/capability" ) func TestRepeatedCapabilityFailuresDegradeSkillWithoutDeletingHistory(t *testing.T) { profile := skillProfile() profile.SupportingExperienceRefs = []capability.SkillEvidenceRef{"experience:success-1"} for _, ref := range []capability.SkillEvidenceRef{"experience:failure-1", "experience:failure-2", "experience:failure-3"} { next, err := ObserveSkillOutcome(profile, capability.SkillOutcomeObservation{ExperienceRef: ref, Outcome: capability.UsageFailed, ObservedAtUnixMillis: profile.RecordedAtUnixMillis + 100}) if err != nil { t.Fatal(err) } profile = next } if profile.Status != capability.SkillDegraded { t.Fatalf("expected degraded skill, got %#v", profile) } if len(profile.SupportingExperienceRefs) != 1 || len(profile.KnownFailureExperienceRefs) != 3 { t.Fatalf("skill degradation must preserve success/failure evidence: %#v", profile) } } func TestFastPathDeclinesUnsupportedInputAndEscalatesToThinking(t *testing.T) { decision, err := DecideFastPath(skillProfile(), false, 900, false, false, 2000) if err != nil { t.Fatal(err) } if decision.Decision != capability.FastPathEscalate || decision.DeclineReason != capability.FastPathOutOfDistribution || !decision.RequiresCognition { t.Fatalf("unexpected fast path decision: %#v", decision) } } func TestValidatedSkillCanApplyFastPathWhenFreshAndConfident(t *testing.T) { decision, err := DecideFastPath(skillProfile(), true, 950, false, false, 2000) if err != nil { t.Fatal(err) } if decision.Decision != capability.FastPathApplied || decision.RequiresCognition { t.Fatalf("unexpected fast path decision: %#v", decision) } } func TestUnknownAndSkippedOutcomesDoNotBecomeSkillFailures(t *testing.T) { profile := skillProfile() for _, outcome := range []capability.UsageOutcomeClass{capability.UsageUnknown, capability.UsageSkipped} { next, err := ObserveSkillOutcome(profile, capability.SkillOutcomeObservation{ExperienceRef: capability.SkillEvidenceRef("experience:" + string(outcome)), Outcome: outcome, ObservedAtUnixMillis: profile.RecordedAtUnixMillis + 1}) if err != nil { t.Fatal(err) } if next.ObservedFailureCount != profile.ObservedFailureCount || len(next.KnownFailureExperienceRefs) != len(profile.KnownFailureExperienceRefs) || next.ConfidenceMillis != profile.ConfidenceMillis { t.Fatalf("outcome %q was incorrectly recorded as failure: %#v", outcome, next) } profile = next } } func skillProfile() capability.SkillProfile { return capability.SkillProfile{ ID: "skill-obvious-reminder-response-v1", Revision: 1, Name: "Resolve obvious reminder continuation", Description: "Use a recent unambiguous reminder/attention target for complete/snooze/cancel without cognition.", ApplicableContext: []string{"continuity:reminder-response"}, ImplementationRef: "continuity:human-response-target-resolver-v1", ImplementationVersion: "1", Status: capability.SkillValidated, ConfidenceMillis: 850, LastValidatedUnixMillis: 1000, RecordedAtUnixMillis: 1000, } }