Add diagnostic trace coverage for intent selection lineage
CI / test (push) Failing after 14s

This commit is contained in:
m
2026-08-18 16:54:46 +03:00
parent b025bec777
commit b6237334c6
2 changed files with 72 additions and 1 deletions
@@ -8,6 +8,7 @@ import (
"git.cin.su/m/Assistant/contracts/identity"
"git.cin.su/m/Assistant/contracts/interaction"
"git.cin.su/m/Assistant/contracts/situation"
"git.cin.su/m/Assistant/platform/ids"
)
func TestInterpretUtteranceRecordsExplicitProjectFocus(t *testing.T) {
@@ -136,6 +137,7 @@ func TestInterpretUtteranceNaturalRussianHelpflowUsesContextAwareCognitionInput(
{message: "нет не UPO а UPO2 и обнови конфиг", wantSpeech: "", wantCognition: true, allowNoMatch: true},
{message: "postgres сейчас работает", wantSpeech: "", wantCognition: true, allowNoMatch: true},
{message: "сейчас домовой не видит ии", wantSpeech: "", wantCognition: true, allowNoMatch: true},
{message: "домовой не видит ии", wantSpeech: "", wantCognition: true, allowNoMatch: true},
{message: "основная база называется UPO", wantSpeech: interaction.SpeechActAssertion, wantCognition: false},
{message: "привет", wantSpeech: interaction.SpeechActConversational, wantCognition: false},
{message: "спасибо", wantSpeech: interaction.SpeechActConversational, wantCognition: false},
@@ -151,6 +153,7 @@ func TestInterpretUtteranceNaturalRussianHelpflowUsesContextAwareCognitionInput(
{message: "домовой не отвечает мне", wantSpeech: "", wantCognition: true, allowNoMatch: true},
{message: "домовой не слушает меня", wantSpeech: "", wantCognition: true, allowNoMatch: true},
{message: "домовой не отвечает на команды", wantSpeech: "", wantCognition: true, allowNoMatch: true},
{message: "ПОЧЕМУ postgres использует так много памяти", wantSpeech: "", wantCognition: true, allowNoMatch: true},
}
for _, tc := range cases {
result := interpretForTest(t, tc.message, nil, "")
@@ -169,6 +172,70 @@ func TestInterpretUtteranceNaturalRussianHelpflowUsesContextAwareCognitionInput(
}
}
func TestInterpretUtteranceDiagnosticTraceLineage(t *testing.T) {
message := "ты кто"
conversation := interaction.Conversation{ID: "conversation-1", ActorID: "actor-1", PrincipalID: "principal-1", Channel: interaction.ChannelWebChat, State: interaction.ConversationOpen}
utterance, _, _, err := NewHumanUtterance(conversation, interaction.ChatMessageRequest{Message: message}, time.Unix(100, 0))
if err != nil {
t.Fatal(err)
}
result, err := InterpretUtterance(utterance, projectRegistryForTest(), nil, time.Unix(100, 0))
if err != nil {
t.Fatal(err)
}
candidateID, err := ids.New()
if err != nil {
t.Fatal(err)
}
cognitiveCandidate := interaction.SemanticCandidate{
ID: interaction.SemanticCandidateID(candidateID),
UtteranceID: utterance.ID,
Source: interaction.CandidateSourceCognitive,
SelectionState: interaction.CandidateObserved,
PrimarySpeechAct: interaction.SpeechActQuestion,
SecondarySpeechAct: interaction.SpeechActUnknown,
ConfidenceMillis: 780,
Applicability: interaction.SemanticNeedsBroaderInterpret,
RequestedOutcome: "",
Clarification: interaction.ClarificationNotRequired,
NeedsCognition: true,
SelectionReason: "trace-oriented cognitive clarification of identity-style intent",
CapabilityHints: []string{"COGNITIVE_REASONING"},
RecordedAtUnixMillis: time.Unix(100, 0).UnixMilli(),
}
selected := ApplyCognitiveCandidate(result, message, cognitiveCandidate, nil)
var deterministic, selectedCandidate *interaction.SemanticCandidate
for index := range selected.Candidates {
c := &selected.Candidates[index]
if c.Source == interaction.CandidateSourceDeterministic {
deterministic = c
}
if c.SelectionState == interaction.CandidateSelected {
selectedCandidate = c
}
}
if deterministic == nil {
t.Fatal("expected deterministic candidate in trace")
}
if selectedCandidate == nil {
t.Fatal("expected selected candidate in trace")
}
if selected.Interpretation.Source != string(interaction.CandidateSourceCognitive) {
t.Fatalf("selection source should switch to cognitive, got %s", selected.Interpretation.Source)
}
if selected.Interpretation.NeedsCognition != selectedCandidate.NeedsCognition {
t.Fatalf("expected selected interpretation cognition=%t got %t", selectedCandidate.NeedsCognition, selected.Interpretation.NeedsCognition)
}
if selected.Interpretation.Clarification != selectedCandidate.Clarification {
t.Fatalf("expected selected candidate clarification to match interpretation clarification")
}
if selectedCandidate.SelectionReason == "" {
t.Fatal("expected clarification/selection reason in selected trace")
}
t.Logf("TRACE deterministic_source=%s cognitive_source=%s selected_source=%s needs_cognition=%t clarification_reason=%s",
deterministic.Source, selectedCandidate.Source, selected.Interpretation.Source, selected.Interpretation.NeedsCognition, selected.Interpretation.SelectionReason)
}
func TestInterpretUtteranceModalExplanationRequestStillRequestsCognition(t *testing.T) {
for _, message := range []string{"можешь расказать об утре", "расскажи об утре", "про утро расскажешь"} {
result := interpretForTest(t, message, nil, "")