- 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 口径一致
57 lines
2.1 KiB
Go
57 lines
2.1 KiB
Go
package memory
|
||
|
||
import "testing"
|
||
|
||
// TestSourceConversation_Roundtrip 证明溯源编码是机器可回溯的:
|
||
// Format 后 Parse 得回同一对真实 id(裁决 04.4.3,design/03 §2)。
|
||
func TestSourceConversation_Roundtrip(t *testing.T) {
|
||
t.Parallel()
|
||
raw := FormatSourceConversation("web:abc", "turn-1")
|
||
|
||
ref, ok := ParseSourceConversation(raw)
|
||
if !ok {
|
||
t.Fatalf("ParseSourceConversation(%q) ok = false, want structured", raw)
|
||
}
|
||
if ref.SessionID != "web:abc" || ref.MessageID != "turn-1" {
|
||
t.Fatalf("parsed ref = %+v, want session web:abc / message turn-1", ref)
|
||
}
|
||
}
|
||
|
||
// TestSourceConversation_BothBlank 证明两个 id 都缺时不落伪溯源
|
||
// (空串而不是空 JSON 对象)。
|
||
func TestSourceConversation_BothBlank(t *testing.T) {
|
||
t.Parallel()
|
||
if got := FormatSourceConversation("", " "); got != "" {
|
||
t.Fatalf("FormatSourceConversation(blank) = %q, want empty", got)
|
||
}
|
||
if _, ok := ParseSourceConversation(""); ok {
|
||
t.Fatal("ParseSourceConversation(\"\") ok = true, want false")
|
||
}
|
||
}
|
||
|
||
// TestSourceConversation_SessionOnly 证明只知会话粒度时溯源降级为
|
||
// 仅 session_id(渠道路径未挂 turn id 时的真实形态)。
|
||
func TestSourceConversation_SessionOnly(t *testing.T) {
|
||
t.Parallel()
|
||
raw := FormatSourceConversation("qq-obv11:group:123", "")
|
||
ref, ok := ParseSourceConversation(raw)
|
||
if !ok {
|
||
t.Fatalf("ParseSourceConversation(%q) ok = false, want structured", raw)
|
||
}
|
||
if ref.SessionID != "qq-obv11:group:123" || ref.MessageID != "" {
|
||
t.Fatalf("parsed ref = %+v, want session-only provenance", ref)
|
||
}
|
||
}
|
||
|
||
// TestSourceConversation_LegacyFreeTextNotStructured 证明裁决前的
|
||
// LLM 自由文本来源解不回结构化形状 —— 调用方靠 ok=false 区分
|
||
// 遗留行与真实溯源,而不是把自由文本误当 id。
|
||
func TestSourceConversation_LegacyFreeTextNotStructured(t *testing.T) {
|
||
t.Parallel()
|
||
for _, legacy := range []string{"conv.1", "昨天聊咖啡时提到的", `["session"]`, `{"other":1}`} {
|
||
if _, ok := ParseSourceConversation(legacy); ok {
|
||
t.Fatalf("ParseSourceConversation(%q) ok = true, want false for legacy free text", legacy)
|
||
}
|
||
}
|
||
}
|