feat(memory): 记忆 P2(项目索引物化 / decay 回写 / 作用域写规则 / 静默吞点 + loop 级只读红线测试)
This commit is contained in:
1 parent
9b903a89bc
commit
509dc412eb
12 files changed
+660
-55
No files matched your search
@@ -0,0 +1,65 @@
|
||||
package loop
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
|
||||
)
|
||||
|
||||
// fixedExtractor(定义见 flow_spans_test.go)返回一组固定条目,用于驱动持久化
|
||||
// 路径的边界断言。
|
||||
|
||||
// TestPersistMemories_ScopedWriteRule_RejectsForeignPersona 钉住审计 2026-10-05
|
||||
// §1.3「Store 作用域写规则未接线」:提取持久化经 Store 的作用域写规则
|
||||
// (AddScoped)落库。一条归属**别的角色**的角色作用域条目必须被拒(ErrReadOnly),
|
||||
// 绝不被冒充成本回合角色的日常记忆。
|
||||
func TestPersistMemories_ScopedWriteRule_RejectsForeignPersona(t *testing.T) {
|
||||
t.Parallel()
|
||||
store := newTestMemoryStore(t)
|
||||
l := New(Options{
|
||||
Memory: store,
|
||||
Extractor: fixedExtractor{items: []memory.MemoryItem{
|
||||
{PersonaID: "persona-b", Scope: memory.ScopePersona, Kind: memory.KindRelationship, Content: "b 的角色日常"},
|
||||
}},
|
||||
PersonaID: "persona-a",
|
||||
})
|
||||
|
||||
ctx := WithSessionEnv(context.Background(), OwnerEnv())
|
||||
l.extractMemory(ctx, []model.Message{model.TextMessage(model.RoleUser, "记住 b 的日常")}, 1)
|
||||
|
||||
items, err := store.List(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("List: %v", err)
|
||||
}
|
||||
if len(items) != 0 {
|
||||
t.Fatalf("跨角色的角色作用域写被接受:%d 条(作用域写规则未接线)", len(items))
|
||||
}
|
||||
}
|
||||
|
||||
// TestPersistMemories_PersonaAgnosticExtractor_StampedByStore 证明接线后正常路径
|
||||
// 不变:与角色无关的提取器(PersonaID 为空)产出的条目仍由 Store 用本回合角色
|
||||
// (actorID)补齐归属,照常落库。
|
||||
func TestPersistMemories_PersonaAgnosticExtractor_StampedByStore(t *testing.T) {
|
||||
t.Parallel()
|
||||
store := newTestMemoryStore(t)
|
||||
l := New(Options{
|
||||
Memory: store,
|
||||
Extractor: fixedExtractor{items: []memory.MemoryItem{
|
||||
{Scope: memory.ScopePersona, Kind: memory.KindRelationship, Content: "主人爱喝冰美式"},
|
||||
}},
|
||||
PersonaID: "persona-a",
|
||||
})
|
||||
|
||||
ctx := WithSessionEnv(context.Background(), OwnerEnv())
|
||||
l.extractMemory(ctx, []model.Message{model.TextMessage(model.RoleUser, "记住 我爱喝冰美式")}, 1)
|
||||
|
||||
items, err := store.ListByPersona(context.Background(), "persona-a")
|
||||
if err != nil {
|
||||
t.Fatalf("ListByPersona: %v", err)
|
||||
}
|
||||
if len(items) != 1 || items[0].PersonaID != "persona-a" {
|
||||
t.Fatalf("角色无关提取器未被 Store 盖章:%+v", items)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user