From 5d4c3877b10b45d198099a440703618a3145310c Mon Sep 17 00:00:00 2001 From: Mikhail Date: Tue, 25 Aug 2026 21:13:26 +0300 Subject: [PATCH] Preserve explicit memory confirmations --- cmd/core-runtime/main.go | 22 ++++++++++++++++++++-- modules/interaction/domain/chat.go | 9 +++++++++ modules/interaction/domain/chat_test.go | 6 ++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/cmd/core-runtime/main.go b/cmd/core-runtime/main.go index b195ad4..13d16ec 100644 --- a/cmd/core-runtime/main.go +++ b/cmd/core-runtime/main.go @@ -620,6 +620,7 @@ func main() { assistantName = latestAssistantName(conversationHistory) } identityReply := "" + memoryInstructionReply := "" log.Printf("interaction identity context: name=%q history=%d", assistantName, len(conversationHistory)) if interactiondomain.IsIdentityInquiry(utterance.Content) && assistantName != "" { identityReply = "Меня зовут " + assistantName + ". Я Домовой, ваш помощник." @@ -629,6 +630,14 @@ func main() { semantic.Interpretation.Applicability = interaction.SemanticApplicable semantic.Interpretation.Clarification = interaction.ClarificationNotRequired } + if identityReply == "" && interactiondomain.IsExplicitMemoryInstruction(utterance.Content) { + memoryInstructionReply = "Запомнил." + semantic.Reply = memoryInstructionReply + semantic.NeedsCognition = false + semantic.CapabilityHints = nil + semantic.Interpretation.Applicability = interaction.SemanticApplicable + semantic.Interpretation.Clarification = interaction.ClarificationNotRequired + } deterministicSpeechAct := semantic.Interpretation.SpeechAct deterministicReply := semantic.Reply routePlan := buildChatRoutePlan(semantic) @@ -643,7 +652,7 @@ func main() { semanticInterpretationRequested = false semanticReflexAudit = false } - if identityReply != "" { + if identityReply != "" || memoryInstructionReply != "" { semanticReflexAudit = false } if semanticInterpretationRequested || semanticReflexAudit { @@ -936,6 +945,10 @@ func main() { planningReply = identityReply needsCognition = false } + if memoryInstructionReply != "" { + planningReply = memoryInstructionReply + needsCognition = false + } if strings.TrimSpace(planningReply) != "" { reviewContext, cancelReview := context.WithTimeout(r.Context(), 12*time.Second) reviewedReply, reviewErr := cognitiveClient.ReviewResponse(reviewContext, session, utterance.Content, planningReply, cognitive.TaskMeaning{ @@ -946,7 +959,7 @@ func main() { ConfidenceMillis: semantic.Interpretation.ConfidenceMillis, }) cancelReview() - stableSemanticReply := mediaAttempted || identityReply != "" || creativeReply != "" || (creativeFallbackReply != "" && !cognitiveAvailable) || semantic.InformationRequestKind != "" || locationReply != "" || deterministicSpeechAct == interaction.SpeechActConversational || deterministicSpeechAct == interaction.SpeechActConfirmation || deterministicSpeechAct == interaction.SpeechActRejection + stableSemanticReply := mediaAttempted || identityReply != "" || memoryInstructionReply != "" || creativeReply != "" || (creativeFallbackReply != "" && !cognitiveAvailable) || semantic.InformationRequestKind != "" || locationReply != "" || deterministicSpeechAct == interaction.SpeechActConversational || deterministicSpeechAct == interaction.SpeechActConfirmation || deterministicSpeechAct == interaction.SpeechActRejection if reviewErr != nil { log.Printf("cognitive response review unavailable: %v", reviewErr) } else if !stableSemanticReply && (!researchBacked || reviewPreservesResearchEvidence(reviewedReply, planningReply)) { @@ -971,6 +984,11 @@ func main() { needsCognition = false planningReply = identityReply } + if memoryInstructionReply != "" { + semantic.Reply = memoryInstructionReply + needsCognition = false + planningReply = memoryInstructionReply + } if creativeReply != "" { semantic.Reply = creativeReply needsCognition = false diff --git a/modules/interaction/domain/chat.go b/modules/interaction/domain/chat.go index d634d30..b52d9bf 100644 --- a/modules/interaction/domain/chat.go +++ b/modules/interaction/domain/chat.go @@ -170,6 +170,15 @@ func IsIdentityInquiry(message string) bool { return containsToken(tokens, "зовут") || containsToken(tokens, "имя") } +// IsExplicitMemoryInstruction recognizes a direct request to retain the +// following human-provided context. It deliberately does not interpret the +// content as a verified fact: the conversation owner keeps the original +// utterance and its provenance. +func IsExplicitMemoryInstruction(message string) bool { + tokens := semanticTokens(message) + return len(tokens) > 0 && containsStem(tokens[0], "запомни", "помни") +} + func BuildDeterministicCandidate(message string, corrects interaction.HumanUtteranceID, millis int64) interaction.SemanticCandidate { id, _ := ids.New() tokens := semanticTokens(message) diff --git a/modules/interaction/domain/chat_test.go b/modules/interaction/domain/chat_test.go index bbd5d99..2a0d5d7 100644 --- a/modules/interaction/domain/chat_test.go +++ b/modules/interaction/domain/chat_test.go @@ -255,6 +255,12 @@ func TestNamingPreferenceIsSemanticAndProducesNaturalAcceptance(t *testing.T) { if !IsIdentityInquiry("ты кто?") || !IsIdentityInquiry("как тебя зовут") { t.Fatal("identity variants should be recognized") } + if !IsExplicitMemoryInstruction("запомни: сокращение — это источник для поиска") { + t.Fatal("explicit memory instruction was not recognized") + } + if IsExplicitMemoryInstruction("что ты помнишь обо мне?") { + t.Fatal("memory inventory question must not be treated as an instruction") + } } func TestMemoryInventoryRequestIsSemantic(t *testing.T) { -- 2.54.0