From 775d9e8a2ea5f373e69eeb9b0764fe200960783a Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Sat, 5 Sep 2026 12:02:34 +0800 Subject: [PATCH] =?UTF-8?q?fix(memory):=20core.New=20=E6=BC=8F=E6=8E=A5=20?= =?UTF-8?q?rc.SetMediaStore=EF=BC=8CL0=E2=86=92L2=20=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E8=BD=AC=E7=A7=BB=E5=9C=A8=E7=94=9F=E4=BA=A7=E4=BB=8E=E6=9C=AA?= =?UTF-8?q?=E7=94=9F=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RelevanceContext.transferMediaRefs 依赖 c.mediaStore,而该字段只有 SetMediaStore() 能设置。搜遍全仓非测试代码,调用点为零——core.New() 里 没有,cmd/homed/main.go 里也没有。 上一层(f855893)把 AgentConfig.MediaStore 接到了 Agent.mediaStore, 漏了 rc 这一路。 后果是静默的:Prune 归档时 c.mediaStore 为 nil,transferMediaRefs 直接 return,而携带引用的 ContextEvent 已被归档删除 → 引用永久悬空在 context owner 上、计数永不归零 → 对应 blob 永远不会被 GC 回收。 ## 为什么测试没抓到 mediaref_test.go 里我手工调了 rc.SetMediaStore(ms) 才测转移逻辑。 **测试验证了函数正确,没验证它被接上了。** 与 findPluginPID 那次同一 个教训:测了一件不会自然发生的事。 ## 顺带全字段审计 写脚本比对 AgentConfig 的 32 个字段与 New() 函数体的引用情况, 确认无第二处漏接。 --- internal/agent/core/agent.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/agent/core/agent.go b/internal/agent/core/agent.go index d97725e..0ad204d 100644 --- a/internal/agent/core/agent.go +++ b/internal/agent/core/agent.go @@ -232,6 +232,12 @@ func New(cfg AgentConfig) *Agent { if cfg.IO != nil { rc.SetChannelDefLookup(cfg.IO.GetInputChannelDef) } + // 必须把媒体存储也注给 RelevanceContext:L0→L2 归档(Prune)靠 + // rc.transferMediaRefs 把引用从 context owner 转给 document owner。 + // 漏了这一行的后果是静默的:rc.mediaStore 为 nil 时转移直接 return, + // 而携带引用的 ContextEvent 已被归档删除 → 引用永久悬空在 + // context owner 上、计数永不归零 → 对应 blob 永远不会被 GC 回收。 + rc.SetMediaStore(cfg.MediaStore) return &Agent{ id: cfg.ID,