Files
Assistant/modules/capability/domain/skill_test.go

76 lines
3.1 KiB
Go

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,
}
}