现象
猫的每轮对话顶部 [导航] 块持续注入 真相源: deploy-irb.py / 下一步: 先看 deploy-irb.py,即使该文件已被删除且与当前 thread 无关。
导致猫被误导去读取不存在的文件,产出串台/幻觉回复。
根因分析
代码路径:packages/api/src/domains/cats/services/agents/routing/route-helpers.ts:729-755
const mem = await threadStore.getThreadMemory(threadId); // ← thread-scoped ✓
const storedLedgerArtifacts = mem.recentArtifacts;
const mergedLedger = mergeLedger(storedLedgerArtifacts, recentArtifacts);
const rankedSources = rankArtifactSources(mergedLedger, ...);
const topSource = rankedSources[0];
问题在 buildThreadMemory.ts 的 artifact ledger 策略:
G1: Artifact ledger — append+dedup+cap (cumulative, not overwrite)
一旦文件路径进入 recentArtifacts ledger,永远不会被移除,即使:
- 文件已删除
- 文件与当前对话完全无关
- 文件来自很久以前的 session
mergeLedger() 只做 append + dedup by ref + cap by count,无文件存在性检查、无 TTL、无过期淘汰。
复现步骤
- 在某 thread 创建临时文件(如
/tmp/deploy-irb.py)
- Session seal 后,文件路径进入
threadMemory.recentArtifacts
- 删除该文件
- 后续所有该 thread 的对话,导航都指向这个已删除的文件
影响
- 猫被误导读取不存在的文件
- 导航失去"指向当前工作上下文"的本来意义
- 用户体验:猫"串台"行为,实际是导航注入层指错路
建议修复
方案 A(推荐):在 rankArtifactSources 前加文件存在性过滤
在 route-helpers.ts:748 后,对 mergedLedger 做文件存在性检查(PR 类型除外)。
方案 B:ledger 加 TTL 过期
在 mergeArtifactLedger() 里加时间窗口——超过 7 天的 artifact 自动淘汰。
方案 C:SessionSealer 写入时过滤已删除文件
在 SessionSealer.ts:412-416 调用 extractRecentArtifacts 前,过滤掉不存在的文件。
相关代码
packages/api/src/domains/cats/services/agents/routing/route-helpers.ts:729-755
packages/api/src/domains/cats/services/agents/routing/artifact-tracking.ts:38-67
packages/api/src/domains/cats/services/agents/routing/source-ranking.ts:40-87
packages/api/src/domains/cats/services/session/buildThreadMemory.ts:68-86
packages/api/src/domains/cats/services/session/SessionSealer.ts:412-425
现象
猫的每轮对话顶部
[导航]块持续注入真相源: deploy-irb.py/下一步: 先看 deploy-irb.py,即使该文件已被删除且与当前 thread 无关。导致猫被误导去读取不存在的文件,产出串台/幻觉回复。
根因分析
代码路径:
packages/api/src/domains/cats/services/agents/routing/route-helpers.ts:729-755问题在
buildThreadMemory.ts的 artifact ledger 策略:一旦文件路径进入
recentArtifactsledger,永远不会被移除,即使:mergeLedger()只做 append + dedup by ref + cap by count,无文件存在性检查、无 TTL、无过期淘汰。复现步骤
/tmp/deploy-irb.py)threadMemory.recentArtifacts影响
建议修复
方案 A(推荐):在
rankArtifactSources前加文件存在性过滤在
route-helpers.ts:748后,对 mergedLedger 做文件存在性检查(PR 类型除外)。方案 B:ledger 加 TTL 过期
在
mergeArtifactLedger()里加时间窗口——超过 7 天的 artifact 自动淘汰。方案 C:SessionSealer 写入时过滤已删除文件
在
SessionSealer.ts:412-416调用extractRecentArtifacts前,过滤掉不存在的文件。相关代码
packages/api/src/domains/cats/services/agents/routing/route-helpers.ts:729-755packages/api/src/domains/cats/services/agents/routing/artifact-tracking.ts:38-67packages/api/src/domains/cats/services/agents/routing/source-ranking.ts:40-87packages/api/src/domains/cats/services/session/buildThreadMemory.ts:68-86packages/api/src/domains/cats/services/session/SessionSealer.ts:412-425