fix(memory,loop): 记忆作用域读写成对 + source_conversation 结构化(裁决 1.9/04.4.2/04.4.3)
- 04.4.2/1.9 读侧:Retrieve 候选集并集 = 本人 persona 域 ∪ user 共享域 ∪ project 共享域(他角色 persona 域仍排除),群聊/陌生人取受限收窄
- 写侧:群聊/陌生人整段跳过记忆提取(可查不可写),persona 域仅属主可写
- 04.4.3:source_conversation 不再由 LLM 自由生成(prompt 不索要、候选结构不含该键),落库时无条件盖真实 {session_id,message_id},编解码集中在 memory/source.go
- 新增跨角色种子用例(原用例即使关掉并集也会通过)+ 成对用例「同群聊上下文:读得到共享域、写不进 store」
- 同步 store.go/retrieve.go 文档注释,与 design/03 §3/§4 口径一致
This commit is contained in:
1 parent
af8591b78a
commit
0ce498754a
11 files changed
+428
-60
No files matched your search
@@ -3,6 +3,7 @@ package memory
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -51,8 +52,10 @@ func TestLLMExtractor_Extract_Parse_正常(t *testing.T) {
|
||||
if items[0].Content != "用户喜欢冰美式" || items[0].Scope != ScopeUser || items[0].Confidence != 0.9 {
|
||||
t.Errorf("items[0] = %+v, want parsed user item", items[0])
|
||||
}
|
||||
if items[0].SourceConversation != "conv.1" {
|
||||
t.Errorf("items[0].SourceConversation = %q, want conv.1", items[0].SourceConversation)
|
||||
// 裁决 04.4.3:模型回填的 source_conversation 被忽略 —— 提取器
|
||||
// 落空溯源,真实 id 由持久化层(loop.persistMemories)盖。
|
||||
if items[0].SourceConversation != "" {
|
||||
t.Errorf("items[0].SourceConversation = %q, want empty (source is stamped by the persistence layer, never the model)", items[0].SourceConversation)
|
||||
}
|
||||
if items[1].ProjectID != "project.alpha" || items[1].Scope != ScopeProject {
|
||||
t.Errorf("items[1] = %+v, want project-scoped item", items[1])
|
||||
@@ -84,6 +87,16 @@ func TestLLMExtractor_Extract_InvalidScopeKind_Fallback_正常(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestLLMExtractor_Prompt_ExcludesSource 锁死提取契约(裁决 04.4.3):
|
||||
// 提取 prompt 不得向模型索要 source_conversation —— 溯源只由持久化层
|
||||
// 盖真实 session/message id,模型自由文本不是来源。
|
||||
func TestLLMExtractor_Prompt_ExcludesSource(t *testing.T) {
|
||||
t.Parallel()
|
||||
if strings.Contains(extractSystemPrompt, "source_conversation") {
|
||||
t.Fatal("extract prompt asks the model for source_conversation: provenance must come from the persistence layer, never the model")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLLMExtractor_Extract_Dedup_正常(t *testing.T) {
|
||||
t.Parallel()
|
||||
// The model emits the same memory three times, differing only in case and
|
||||
|
||||
Reference in new issue
Block a user